C 来自访谈的指针字符串解释的Printf输出

C 来自访谈的指针字符串解释的Printf输出,c,string,pointers,printf,C,String,Pointers,Printf,我接受了一次采访,我收到了这段代码,问我这些printf语句的输出是什么 我的答案是评论,但其余的我不确定 有人能解释语句1、3和7的不同输出吗?为什么 谢谢大家! #include <stdio.h> int main(int argc, const char * argv[]) { char *s = "12345"; printf("%d\n", s); // 1.Outputs "3999" is this the address of the

我接受了一次采访,我收到了这段代码,问我这些printf语句的输出是什么

我的答案是评论,但其余的我不确定

有人能解释语句1、3和7的不同输出吗?为什么

谢谢大家!

#include <stdio.h>

int main(int argc, const char * argv[]) {

    char *s = "12345";

    printf("%d\n", s);      // 1.Outputs "3999" is this the address of the first pointer?
    printf("%d\n", *s);     // 2.The decimal value of the first character
    printf("%c\n", s);      // 3.Outputs "\237" What is this value?
    printf("%c\n", *s);     // 4.Outputs "1"
    printf("%c\n", *(s+1)); // 5.Outputs "2"
    printf("%s\n", s);      // 6.Outputs "12345"
    printf("%s\n", *s);     // 7.I get an error, why?
    return 0;
}

第7行失败,因为需要一个C样式的字符串作为输入,而您正在放置一个字符

看看:


第7行失败,因为需要一个C样式的字符串作为输入,而您正在放置一个字符

看看:

为了运行您的代码,我使用了以下命令:, 结果如下:

1. 4195988            - undefined behaviour (UB), manifesting here as the address
                        of the char array as you stated (for a 64 bit address you might or
                        might not get truncation)
2. 49                 - ASCII value of '1'
3. �                  - undefined behaviour, manifesting here as unsupported ASCII value
                        for a truncation of the address of the array of chars
                        (placing 32-bit address into a char - assuming a 32-bit system)
4. 1                  - obvious
5. 2                  - obvious
6. 12345              - obvious
7. Segmentation fault - undefined behaviour, trying to place the first char
                        of a char array into a string reserved position
                        (placing char into a string)
注意第3点:我们可以推断在运行时发生了什么。 在问题中提供的具体示例中-

printf("%c\n", s);      // 3.Outputs "\237". What is this value?
这是处理UB时与硬件/编译器/操作系统相关的行为

为什么??由于输出\237->这意味着执行此代码的特定硬件系统下的截断

请参见下面的说明-32位系统:

char *s = "12345"; // Declaring a char pointer pointing to a char array
char c = s; // Placement of the pointer into a char - our UB
printf("Pointer to character array: %08x\n", s); // Get the raw bytes
printf("Pointer to character: %08x\n", c); // Get the raw bytes
printf("%c\n", s); // place the pointer as a character
                   // display is dependent on the ASCII value and the OS
                   // definitions for 128-255 ASCII values
产出:

Pointer to character array: 004006e4  // Classic 32-bit pointer
Pointer to character: ffffffe4        // Truncation to a signed char
                                      // (Note signed MSB padding to 32 bit display)
�                                     // ASCII value E4 = 228 is not displayed properly
最后的printf命令相当于char c=s;printf%c\n,c;。 为什么?多亏了截断

具有合法ASCII字符输出的附加示例:

    char *fixedPointer = 0xABCD61; // Declaring a char pointer pointing to a dummy address
    char c = fixedPointer; // Placement of the pointer into a char - our UB
    printf("Pointer to 32-bit address: %08x\n", fixedPointer); // Get the raw bytes
    printf("Pointer to character: %08x\n", c); // Get the raw bytes
    printf("%c\n", fixedPointer);
以及实际产出:

Pointer to 32-bit address: 00abcd61
Pointer to character: 00000061
a
为了运行您的代码,我使用了以下命令:, 结果如下:

1. 4195988            - undefined behaviour (UB), manifesting here as the address
                        of the char array as you stated (for a 64 bit address you might or
                        might not get truncation)
2. 49                 - ASCII value of '1'
3. �                  - undefined behaviour, manifesting here as unsupported ASCII value
                        for a truncation of the address of the array of chars
                        (placing 32-bit address into a char - assuming a 32-bit system)
4. 1                  - obvious
5. 2                  - obvious
6. 12345              - obvious
7. Segmentation fault - undefined behaviour, trying to place the first char
                        of a char array into a string reserved position
                        (placing char into a string)
注意第3点:我们可以推断在运行时发生了什么。 在问题中提供的具体示例中-

printf("%c\n", s);      // 3.Outputs "\237". What is this value?
这是处理UB时与硬件/编译器/操作系统相关的行为

为什么??由于输出\237->这意味着执行此代码的特定硬件系统下的截断

请参见下面的说明-32位系统:

char *s = "12345"; // Declaring a char pointer pointing to a char array
char c = s; // Placement of the pointer into a char - our UB
printf("Pointer to character array: %08x\n", s); // Get the raw bytes
printf("Pointer to character: %08x\n", c); // Get the raw bytes
printf("%c\n", s); // place the pointer as a character
                   // display is dependent on the ASCII value and the OS
                   // definitions for 128-255 ASCII values
产出:

Pointer to character array: 004006e4  // Classic 32-bit pointer
Pointer to character: ffffffe4        // Truncation to a signed char
                                      // (Note signed MSB padding to 32 bit display)
�                                     // ASCII value E4 = 228 is not displayed properly
最后的printf命令相当于char c=s;printf%c\n,c;。 为什么?多亏了截断

具有合法ASCII字符输出的附加示例:

    char *fixedPointer = 0xABCD61; // Declaring a char pointer pointing to a dummy address
    char c = fixedPointer; // Placement of the pointer into a char - our UB
    printf("Pointer to 32-bit address: %08x\n", fixedPointer); // Get the raw bytes
    printf("Pointer to character: %08x\n", c); // Get the raw bytes
    printf("%c\n", fixedPointer);
以及实际产出:

Pointer to 32-bit address: 00abcd61
Pointer to character: 00000061
a
这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
具有未定义的行为,因为指针使用了无效的格式说明符

这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
输出内部代码,例如字符“1”的ASCII代码

这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
由于使用无效的格式说明符和指针,具有未定义的行为

这些电话

printf("%c\n", *s);
printf("%c\n", *(s+1));
是有效的。第一个输出字符“1”,第二个输出字符“2”

这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
正确,并输出字符串12345

这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
无效,因为无效的格式说明符用于char类型的对象。

此调用

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
具有未定义的行为,因为指针使用了无效的格式说明符

这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
输出内部代码,例如字符“1”的ASCII代码

这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
由于使用无效的格式说明符和指针,具有未定义的行为

这些电话

printf("%c\n", *s);
printf("%c\n", *(s+1));
是有效的。第一个输出字符“1”,第二个输出字符“2”

这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
正确,并输出字符串12345

这个电话

printf("%d\n", s); 
printf("%d\n", *s);
printf("%c\n", s);
printf("%s\n", s);
printf("%s\n", *s);
无效,因为无效的格式说明符与char类型的对象一起使用

此代码未定义。您正在传递一个指针,其中函数需要一个int值。例如,在64位体系结构中,指针是64位的,int是32位的。可以打印截断的值

您正在传递编译器自动转换为int的第一个char值,并以十进制打印它。可能您得到了“1”的ASCII码。这是合法使用,但要小心意外,因为如果您的平台字符实现被签名,您可能会得到负值

您正在打印传递的指针,该指针被重新解释为char值。未定义的行为,因为无法将指针转换为char值

您正在将s的点值打印为字符,因此将获得字符串12345“1”的第一个字符

您正在打印由s指向的第一个字符旁边的字符,因此得到字符串“2”的第二个字符

您正在打印由s指向的字符串,因此可以得到整个字符串。这是合法的,实际上是打印字符串的常用方法

您正在传递字符串的第一个字符,该字符串将被解释为指向要打印的以null结尾的字符串的指针,而该字符串不是。这又是一种未定义的行为。您正在将char值重新解释为指向以null结尾的字符串的指针。SIGSEGV在这种情况下很常见,但不保证:当程序在到达终止字符串的假定空字符之前尝试访问未分配的内存时,会发送信号,但它可能会在途中找到“\0”,而只是打印垃圾

此代码未定义。您正在传递一个指针,其中函数需要一个int值。例如,在64位体系结构中,指针为64位,int为32位 T可以打印截断的值

您正在传递编译器自动转换为int的第一个char值,并以十进制打印它。可能您得到了“1”的ASCII码。这是合法使用,但要小心意外,因为如果您的平台字符实现被签名,您可能会得到负值

您正在打印传递的指针,该指针被重新解释为char值。未定义的行为,因为无法将指针转换为char值

您正在将s的点值打印为字符,因此将获得字符串12345“1”的第一个字符

您正在打印由s指向的第一个字符旁边的字符,因此得到字符串“2”的第二个字符

您正在打印由s指向的字符串,因此可以得到整个字符串。这是合法的,实际上是打印字符串的常用方法

您正在传递字符串的第一个字符,该字符串将被解释为指向要打印的以null结尾的字符串的指针,而该字符串不是。这又是一种未定义的行为。您正在将char值重新解释为指向以null结尾的字符串的指针。SIGSEGV在这种情况下很常见,但不保证:当程序在到达终止字符串的假定空字符之前尝试访问未分配的内存时,会发送信号,但它可能会在途中找到“\0”,而只是打印垃圾


我必须指出,这次采访是一个悲伤的笑话。你面试的公司正在招聘编译器,而不是软件工程师。这是一个基本问题,看看我是否了解printf的基本知识以及不同的类型和调用。我建议你尝试另一个工作场所。我很乐意详细解释为什么会这样。我必须指出——这次采访是一个悲伤的笑话。你面试的公司正在招聘编译器,而不是软件工程师。这是一个基本问题,看看我是否了解printf的基本知识以及不同的类型和调用。我建议你尝试另一个工作场所。我很乐意详细解释为什么会这样。即使假设是32位系统,代码如char*s=12345;打印指向字符数组的指针:%08x\n,s;保持未定义的行为,并且不是可靠的合法ASCII字符输出。这样的代码缺乏未来的正确性和可维护性,即使它最初按预期工作。应该清楚地将其标识为UB,尤其是在面试问答中。IOW,对UB如何发生的详细解释,在面试过程中,没有强调代码根本不足的重要性。@chux:核心原则很简单-不要对UB进行编码。永远不要编写任何源于UB的代码。我见过UB引起的可怕的错误/副作用,并一直试图与之抗争。时期新线。在求职面试中,如果被问及某一行为,在明确这确实是UB之后——你可以通过解释UB造成的原因来表现出更深刻的理解;打印指向字符数组的指针:%08x\n,s;保持未定义的行为,并且不是可靠的合法ASCII字符输出。这样的代码缺乏未来的正确性和可维护性,即使它最初按预期工作。应该清楚地将其标识为UB,尤其是在面试问答中。IOW,对UB如何发生的详细解释,在面试过程中,没有强调代码根本不足的重要性。@chux:核心原则很简单-不要对UB进行编码。永远不要编写任何源于UB的代码。我见过UB引起的可怕的错误/副作用,并一直试图与之抗争。时期新线。在求职面试中,如果被问及某个行为,在明确表示确实是UB之后——你可以通过解释UB造成的原因来表现出更深刻的理解。