该声明
printf("%f\n",0.0f);
Run Code Online (Sandbox Code Playgroud)
打印0.
但是,声明
printf("%f\n",0);
Run Code Online (Sandbox Code Playgroud)
打印随机值.
我意识到我表现出某种未定义的行为,但我无法弄明白为什么具体.
所有位都为0的浮点值仍然有效float,值为0.
float并且int在我的机器上具有相同的大小(如果它甚至相关).
为什么使用整数文字而不是浮点文字printf会导致此行为?
如果我使用PS,可以看到相同的行为
int i = 0;
printf("%f\n", i);
Run Code Online (Sandbox Code Playgroud) 我希望这可以工作,但它没有:
#include <stdio.h>
typedef struct closure_s {
void (*incrementer) ();
void (*emitter) ();
} closure;
closure emit(int in) {
void incrementer() {
in++;
}
void emitter() {
printf("%d\n", in);
}
return (closure) {
incrementer,
emitter
};
}
main() {
closure test[] = {
emit(10),
emit(20)
};
test[0] . incrementer();
test[1] . incrementer();
test[0] . emitter();
test[1] . emitter();
}
Run Code Online (Sandbox Code Playgroud)
它实际上并编译和1个实例不工作...但第二个失败.知道如何在C中获得闭包吗?
真的很棒!
我想拿起一点x86.我正在使用gcc -S -O0在64位mac上进行编译.
C中的代码:
printf("%d", 1);
Run Code Online (Sandbox Code Playgroud)
输出:
movl $1, %esi
leaq LC0(%rip), %rdi
movl $0, %eax ; WHY?
call _printf
Run Code Online (Sandbox Code Playgroud)
我不明白为什么在调用'printf'之前%eax被清除为0.由于printf返回打印的字符数量为%eax我最好的猜测,因此将其归零以准备它,printf但我认为printf必须负责准备它.而且,相反,如果我调用自己的功能int testproc(int p1),则gcc认为没有必要准备%eax.所以我想知道为什么gcc对待printf和testproc不同.
在我的C++ JNI-Agent项目中,我正在实现一个函数,该函数将被赋予可变数量的参数并将执行传递给另一个函数:
// address of theOriginalFunction
public static void* originalfunc;
void* interceptor(JNIEnv *env, jclass clazz, ...){
// add 4 to the function address to skip "push ebp / mov ebp esp"
asm volatile("jmp *%0;"::"r" (originalfunc+4));
// will not get here anyway
return NULL;
}
Run Code Online (Sandbox Code Playgroud)
上面的函数只需要跳转到:
JNIEXPORT void JNICALL Java_main_Main_theOriginalFunction(JNIEnv *env, jclass clazz, jboolean p1, jbyte p2, jshort p3, jint p4, jlong p5, jfloat p6, jdouble p7, jintArray p8, jbyteArray p9){
// Do something
}
Run Code Online (Sandbox Code Playgroud)
上面的代码工作正常,原始函数可以正确读取所有参数(使用包括数组在内的9种不同类型的参数进行测试).
但是,在从拦截器跳入原始函数之前,我需要做一些计算.但是,在这里我观察到有趣的行为.
void* interceptor(JNIEnv *env, jclass …Run Code Online (Sandbox Code Playgroud) 在 C 中,定义可变长度参数的唯一方法是使用省略号声明其原型并使用va_list, va_start, va_arg,va_end来提取它们。就像printf系列和scanf系列一样。
在 C++11 中,引入了一种新方法,如下所示。
template <typename T, typename... MoreT>
void func(T arg, MoreT... args){
// Do some stuff
func(args);
}
Run Code Online (Sandbox Code Playgroud)
每种方法的优点和缺点是什么?在 C++ 中是否不鼓励使用或鼓励它们中的任何一个?
尝试编译此代码时
#include <stdarg.h>
void bar_ptr(int n, va_list *pvl) {
// do va_arg stuff here
}
void bar(int n, va_list vl) {
va_list *pvl = &vl; // error here
bar_ptr(n, pvl);
}
void foo(int n, ...) {
va_list vl;
va_list *pvl = &vl; // fine here
va_start(vl, n);
bar(n, vl);
va_end(vl);
}
int main() {
foo(3, 1, 2, 3);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC 编译器会initialization from incompatible pointer type在bar函数中打印一条警告。相同的语句在foo.
似乎 type 的 agument 的类型va_list不是 …
我的问题是我想创建一个通用命令行应用程序,可用于加载库DLL,然后调用库DLL中的函数.函数名称在命令行中指定,参数也在实用程序命令行中提供.
我可以从使用该LoadLibrary()函数动态加载的DLL访问外部函数.一旦加载了库,我就可以获得一个指向函数的指针,GetProcAddress()我希望用命令行中指定的参数调用该函数.
我可以将一个void-pointer-list传递给函数指针,该函数指针是由LoadLibrary()类似下面示例的函数返回的?
为了简化示例代码,我删除了错误检查.有没有办法让这样的工作:
//Somewhere in another dll
int DoStuff(int a, int b)
{
return a + b;
}
int main(int argc, char **argv)
{
void *retval;
void *list = argv[3];
HMODULE dll;
void* (*generic_function)(void*);
dll = LoadLibraryA(argv[1]);
//argv[2] = "DoStuff"
generic_function = GetProcAddress(dll, argv[2]);
//argv[3] = 4, argv[4] = 7, argv[5] = NULL
retval = generic_function(list);
}
如果我忘记提及必要的信息,请告诉我.提前致谢
如果我定义了一个可变函数:
#include <stdio.h>
#include <stdarg.h>
int f(char*s,...)
{
va_list ap;
int i=0;
va_start(ap, s);
while(s)
{
printf("%s ", s);
i++;
s=va_arg(ap,char*);
}
va_end(ap);
return i;
}
int main()
{
return f("a","b",0);
}
Run Code Online (Sandbox Code Playgroud)
gcc(linux x64)编译这个,exe运行并打印"ab".
有没有需要像以下一样的演员:
return f("a","b",(char*)0)
Run Code Online (Sandbox Code Playgroud)
在共同的系统上?