【发布时间】:2021-05-26 20:39:21
【问题描述】:
例如,以下代码在编译时返回错误和警告,在更改为 %d 时返回 int
警告: 格式
%s需要char *类型的参数,但参数 2 的类型为int
void stringd() {
char *s = "Hello";
printf("derefernced s is %s", *s);
}
【问题讨论】:
标签: c
例如,以下代码在编译时返回错误和警告,在更改为 %d 时返回 int
警告: 格式
%s需要char *类型的参数,但参数 2 的类型为int
void stringd() {
char *s = "Hello";
printf("derefernced s is %s", *s);
}
【问题讨论】:
标签: c
*s 是 char 类型的表达式,因为它是应用于指向 char1 的指针的取消引用运算符。结果,当传递给printf 时,它会将promoted 转换为int;为了打印以 null 结尾的字符串,您需要将指针传递给第一个字符(即 s)。
1 即使s 不是 const 指针,您也不应该尝试修改它指向的字符,因为它们可能被放置在只读内存中,其中字符串文字存储在某些架构/环境;有关详细信息,请参阅this discussion。
【讨论】:
变量s 是一个指针,指向在内存中连续的一系列字符中的第一个(通俗地称为“字符串”,尽管它并不完全相同)。它是一个指向字符的指针,因此是char *。
取消引用s(通过执行*s)为您提供这些字符中的第一个h,其类型现在只是char。一层间接被剥离。
因此,问题在于您尝试传递一个字符 (char),而该字符应为字符串 (char *)。 char * 是预期的,因为您在 printf 的格式字符串中使用了 %s 类型字符。相反,您应该使用%c,它需要单个、简单的char。
这里的错误实际上是相当严重的。如果您被允许在预期 char * 的地方传递 'h',那么您最终会在预期指针的地方传递 'h' (0x68) 的 ASCII 码。 printf 将不明智,并会尝试取消引用该值,将 0x68 视为指向字符串开头的指针。当然,这可能不是您程序中的有效内存位置,因此如果允许发生,这应该会导致非常可靠的 seg-fault。
【讨论】: