这是代码
void test(char *bar) {
printf("%s", bar);
}
int main(int x, char *argv[]) {
test(argv[0])
return 0;
}
argv[]
是一个指针数组,argv[0]
获取数组中的第一个指针。
在test(char *whatever)
中使用时,因为它是一个指针,我认为它会打印内存地址,而不是值。 (为了获得价值,你会printf("%s,*whatever)
是否正在进行类型转换?我误解了指针是如何工作的吗?
答案 0 :(得分:4)
%s
printf
格式说明符需要指向字符串的指针(即以空字节结尾的字符数组的第一个元素的地址)并打印该字符串。
如果要打印指针值,请使用%p
格式说明符。
printf("%p", (void *)bar);
请注意,此处需要转换为void *
指针,这是需要进行此类转换的少数几次之一。
答案 1 :(得分:3)
不,你弄错了,%s
转换说明符需要空终止字符数组的第一个元素的地址,并打印数组的内容,直到找到空终止符。
引用C11
章节§7.21.6.1
s
如果不存在
l
长度修饰符,则参数应为指向初始值的指针 字符数组的元素.280)数组中的字符是 写入(但不包括)终止空字符。 [....]
的确,如果你想打印一个地址,你必须
%p
转换说明符void *
。参考,同章,
p
参数应是指向
void
的指针。指针的值是 转换为一系列打印字符,在实现定义中 方式。
在这个特定的情况下,参数是一个指向char的指针,如章节§6.2.5中所述,指向void的指针和指向具有相同表示和对齐要求的字符类型的指针,它在这里是可以互换的并且强制转换不是必须的,但是如果指向其他类型的指针(不兼容)必须有强制转换
答案 2 :(得分:0)
"%s"
需要一个指针作为参数。它将从指针的值开始读取,直到找到'\0'
,并且一次只能转换一个字符。
因此它需要一个地址,但它不会打印地址,它会打印指针所指向的字符串。
答案 3 :(得分:0)
指针 是包含内存地址的变量。因此,如果要打印内存地址,则需要打印此变量包含的值。您可以在printf中使用任何数字格式来执行此操作,但是有一个特殊的指针:%p
。虽然在大多数系统中都不需要它,但它是一种将其转换为(void*)
的可移植方式。
当你使用*pointer
这样的东西时,你要求编译器获取该指针所指向的内存中的第一个值。结果的类型取决于指向的指针。因此,在char *pointer
中,操作将返回一个char。它绝对等同于pointer[0]
。因此,在您的示例中,printf("%s", *whatever)
可能会崩溃,因为printf将尝试将第一个字符的值解释为字符串的地址。但是,您可以按以下方式打印此字符:printf("%c", *whatever)