2015-05-30 39 views
0

我期待编译错误,考虑到必须在%p中分配一个指针,但是当我有意将一个指针指向%s时,下面的代码不会给出错误。通过添加&符号&,右边它应该生成数组的地址并将内存地址分配给%p,而不是给出字符串的值。除非我取消引用指针,但是我根本不解引用指针,我从来没有在printf中的my_pointer前面加上星号*。指定字符串类型的指针类型

#include <stdio.h> 
int main() 
{ 
    char words[] = "Daddy\0Mommy\0Me\0"; 
    char *my_pointer; 
    my_pointer = &words[0]; 

    printf("%s \n", my_pointer); 
    return 0; 

} 

请看看这个:

printf("%s \n", my_pointer); 

我的理解是,* my_pointer(带*号)应该给我的字符串值。 但my_pointer(不带星号)不应该给我的字符串的值,但它应该只给我的内存地址,但是当我运行这个代码时,我得到了字符串eventhough的值,但我没有把星号*在前面。我希望这一次让我自己清醒。

+0

您不能“分配”指向“printf”格式说明符的指针; '%s'想要一个'char *',这就是你给它的。 – szczurcio

+2

我没有看到什么似乎是问题。 %s表示const char *参数 –

回答

2

这里:

printf("%s \n", my_pointer); 

%s,期望一个char*并且由于my_pointerchar*指向阵列保持一个NUL终止的字符串,所述printf没有问题,并且是完全有效的。从C11标准(重点煤矿)相关报价:

7.21.6.1 fprintf函数

[...]

  • 转换标识符它们的含义如下:

    s - 如果没有l长度修饰符存在,则参数应该是指向字符类型为的数组元素的初始。 280)来自该数组的字符是 写成(但不包括)终止空字符。如果指定了 精度,则不会写入超过这么多的字节。如果 精度未指定或大于数组的大小,则数组应包含空字符 。
    [...]

  • IMO,你被迷惑在这里:

    考虑到指针在%p来进行分配,但下面的代码不会给我错误,当我故意指定一个指针到%s时

    首先,%s,%p等都是转换说明符。它们用于某些功能,如printf,scanf
    接下来,您是指定指针类型的人。所以在这里:

    my_pointer = &words[0]; 
    

    &words[0]以及my_pointerchar*类型。因此,分配这两个是完全有效的,因为两者都是相同的类型。

    +0

    OT,但粗体文本似乎表示'printf(“%s \ n”,my_pointer + 1);'会是UB,因为该指针不指向初始元素! –

    +0

    它并不是说它是UB,但你是对的。你认为我应该做什么或大胆? –

    +0

    这是另一个实验,仍然与我的问题有关:int a; int * pointer_to_a; pointer_to_a =&a printf(“我的地址是%d \ n”,pointer_to_a); return 0; 错误:%d期望一个mathing'int'参数(但为什么%s不会产生错误) – user4951761

    0

    在c中,数组名也是第一个元素的指针,意思是在你的情况下words&words[0]当作为指针时,它们具有相同的值。

    而且,你将它分配给另一个相同类型的指针,所以这是合法的。

    关于c中的字符串,它只是一个以'\0'结尾的字符数组,它的名称指针指向第一个字符。

    0

    编译器完全按照需要处理您的代码。

    %s格式说明符告诉printf()预期const char *作为相应的参数。然后它认为指针是数组char的第一个元素的地址,并且每找到一个char就会发现它,直到它遇到值为零的一个('\0')。

    严格来说,编译器甚至不需要检查my_pointer是或可以隐式转换为const char *。但是,大多数现代编译器(假设格式字符串是在编译时提供的)执行此操作。