我想知道是否:
void *ptr = NULL;
printf("%p\n", ptr);
Run Code Online (Sandbox Code Playgroud)
会不会给出(nil)输出?
它是依赖于标准库实现,还是C99标准规范?
我正在创建一个修改过的printf实现,我不确定这些问题的答案.
零是否作为空字符串工作?(被printf("%s", 0)允许吗?)
我猜不是,因为0是一个int.但是这会引发这个问题:
是否NULL作为空字符串?(被printf("%s", NULL)允许吗?)
从逻辑上讲,我认为它应该是肯定的,因为它NULL意味着指针; 但是很多实现似乎都有#define NULL 0,所以我觉得在实践中可能没有.哪个是对的?
指针类型是否必须指向char?(被printf("%s", (void const *)"")允许吗?)
我的猜测是类型并不重要,但我不确定.
如果我编译这个程序:
#include <stdio.h>
int main(int argc, char** argv) {
printf("hello world!\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于x86-64,asm输出使用movl $.LC0, %edi/ call puts.(请参阅godbolt上的完整asm输出/编译选项.)
我的问题是:GCC如何知道字符串的地址可以适合32位立即数操作数?为什么不需要使用movabs $.LC0, %rdi(即a mov r64, imm64,不是零或符号扩展imm32).
AFAIK,没有任何迹象表明加载器必须决定在任何特定地址加载数据部分.如果字符串存储在上面的某个地址,1ULL << 32那么movl将忽略更高的位.我对clang有类似的行为,所以我不认为这是GCC独有的.
我关心的原因是我想创建自己的数据段,它存在于我选择的任意地址(可能超过2 ^ 32)的内存中.
#include<stdio.h>
#include<string.h>
int main() {
char *ptr = NULL;
printf("%s", ptr);//The output is null
// printf("%s\n", ptr); //addition of **\n** give segmentation fault
return 0;
}
Run Code Online (Sandbox Code Playgroud)
第一个printf输出:(null).但为什么第二个printf产出是: Segmentation fault (core dumped)只是添加:\n?
为什么函数在将其作为字符串printf分配给它时返回 6 而不是 0 ,尽管它什么也没打印?NULL
int main(void)
{
int x;
x = printf("%s", NULL);
printf ("\n%d", x);
}
Run Code Online (Sandbox Code Playgroud)
输出是:
(null)
6
Run Code Online (Sandbox Code Playgroud)