繁体   English   中英

C编程指针

[英]C Programming Pointers

我不明白为什么最后一个代码块生成1819043176 1870078063 6581362 0 1 2 3 4 0 6488159 ...这些数字不是随机的,但是为什么这些数字呢? 谢谢!

int main(void) {
    int x;
    int y[10];
    int* p;
    char* q;
    int k;
    char* prefix;

    k = 0;
    while (k < 10) {
            y[k] = k;
            k = k + 1;
    }
    x = 42;
    printf("address of y are %d %d %d\n", y, y + 1, y + 9);
    doit(y + 1);

    p = &y[0];
    printf("p is %d\n", p);
    *p = 42;
    p = p + 9;
    printf("p is %d\n", p);
    *p = 17;

    q = "hello world";
    p = "hello world";
    k = 0;
    while (k < 10) {
            printf("%d ", q[k]);
            k = k + 1;
    }
    printf("The end\n");

    k = 0;
    while (k < 10) {
            printf("%d ", p[k]);
            k = k + 1;
    }
    printf("The end\n");
}

void doit(int p[9])
{
    char* prefix = "";
    int k = 0;
    printf("p is %d at address %d\n", p, &p);
    while (k < 10)
    {
        printf("%s%d", prefix, *p);
        prefix = ", ";
        k = k + 1;
        p = p + 1;
    }
    printf("\n");
}

1819043176是十六进制的6C6C6568,将其作为字节68、65、6c,6c存储在小字节序机器上。 这是“ hello world”的前四个字符。 等等。

通常,您不应该在C中执行这些操作,结果是不确定的或与实现有关的。

但是,如果您仍然想在内存中窥视一下,那么最好以更系统的方式进行操作,例如编写一个小的实用程序来进行十六进制转储。

我没有为您提供足够的答案,但是我有一个重要建议: 加快编译器的警告。 当我的bash启动时,它将gcc别名为/usr/bin/gcc -Wall -Wextra -Werror这样,我尝试编译的任何内容都必须通过GCC的最严格的测试(并且将所有警告均视为错误,因此是小错误)将无法编译)。 您的代码给了我一英里长的错误打印输出(不是字面上的意思)。 一些错误:

  • printf()有一个特殊的指针格式说明符: %p 不要使用%d这是用于int的。
  • p是一个int * (指针到一个int ), "hello world"是一个char * 您可以将一个分配给另一个,但这通常不是一个好主意,因此,如果您确实想这样做,则应该使用强制转换说“嘿,我的意思是这样做:” p = (int *) "hello world";
  • main()不返回void ,它返回一个int 您知道这一点,因为您像一个好的程序员一样声明了int main(void) ,但随后我们到了main()的结尾,没有return语句! 如果您不return任何内容,应该如何返回int 在C ++中,我们可以跳过结尾的return语句,但是在C语言中则不能(至少,我们确实不应该这样做,因为可能会发生不好的事情)。

另外,您有一个经常重复的模式:

k = 0;
while (k < 10) {
        y[k] = k;
        k = k + 1;
}

欢迎使用for循环:

for(k = 0; k < 10; k++) {
        y[k] = k;
}

for()循环包含三个部分:

for(init; cond; inc)

init在循环之前运行一次,然后只要cond为true,循环就会执行,并在每个循环结束时执行inc 它几乎完全等同于您正在做的事情,并且更加简洁。

您有p指向字符串“ hello world”
但您已将p定义为指向整数的指针,因此p看起来像这样

p[0] = 'hell'
p[1] = 'o wo'
p[2] = 'rldx'
p[3] = 'xxxx'
p[4] = 'xxxx'
p[5] = 'xxxx'
p[6] = 'xxxx'
p[7] = 'xxxx'
p[8] = 'xxxx'
p[9] = 'xxxx'

where xxxx means you have not set this memory to anything.

lets look at p[0]
h=0x68
e=0x65
l=0x6c
l=0x6c

so you have the hexidecimal number 0x6c6c6568 which you can check is 1819043176

and so on

(a)打印数字和(b)数字不是随机的原因是因为在最后一个代码块中,您试图将字符串打印为小数。 毕竟,这就是%d期望打印的内容-小数。 这与指针没有任何关系。

您没有说期望输出什么,但是您必须选择正确的格式化程序来实现。

另一个建议-在C和C ++中增加变量的通常习惯用法是

++x;

要么

x++;

将值增加1并

x += 9;

将其增加1以上(在这种情况下,显然是9)。

我认为这是因为当格式字符串期望整数时,您正在将char传递给printf。 尝试将q [k]和p [k]转换为整数。

while (k < 10) {
        printf("%d ", (int)p[k]);
        k = k + 1;
}

对printf()的调用不是正常的函数调用,它使用varargs / stdargs,在这些函数中,该函数需要解压缩正确的类型。

因此,输出中的第一个数字1819043176对应于0x6C6C6568。 看看您大概希望看到的小写字母'h'(0x68)的字符值如何是四字节整数中的最低有效字节? 这是因为varargs例程由于%d格式说明符而期望使用整数大小的参数。

这并没有按照您的想法做(我希望,也许):

while (k < 10) {
        printf("%d ", q[k]);
        k = k + 1;
}

考虑一下q是什么,printf做什么,以及%d的含义(提示,看一下q的赋值)。 我还建议您包含期望结果的输出,因为从代码中您实际要完成的目标并不明显(除了使用printf而不是int打印指向int的指针外)。

您的问题与变量p有关。 它是int *,整数变量的sizeof是4个字节(可能会因系统和编译器而异),但是sizeof(char)是1个字节

“ hello world”字符串为12个字节-带空值-可以3个整数定义12个字节。

在这行之后

p = "hello world";

p仅使用3 * 4内存。 (* p点数组“ y”)其余的将为null ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM