简体   繁体   English

C中的指针,指向字符指针的整数指针

[英]Pointers in C, integer pointer to character pointer

When I run this code: 当我运行此代码时:

int arr[3] = {2,3,4};
char *p;
p = (char*)arr;
printf("%d", *p);
p = p+1;
printf("%d", *p);

The output is 2 and 0. The second result is slightly confusing. 输出为2和0.第二个结果有点令人困惑。 Could someone explain why this is happening? 有人可以解释为什么会这样吗?

Let's break this down: 让我们打破这个:

int arr[3] = {2,3,4};

Creates an array of 3 integers. 创建一个包含3个整数的数组。 Assuming your system is 32bit little endian this is how it looks in memory: 假设您的系统是32位小端,这就是它在内存中的外观:

02 00 00 00 03 00 00 00 04 00 00 00

char *p; p = (char*)arr;

p now points to arr but is a pointer to char* . p现在指向arr但是指向char*的指针。 In other words, p points to the 02 . 换句话说, p指向02

printf("%d", *p);

You are printing as an int the location referenced by p . 您将作为int打印由p引用的位置。 So when you dereference p (by writing *p ) you are accessing the char (since p is of type char* ) referenced by p . 因此,当您取消引用 p (通过写*p )时,您正在访问由p引用的char (因为pchar*类型)。 Which is 02 . 这是02

p = p+1;

p now points to the 00 just after 02 , because p is char* . p现在指向02之后的00 ,因为pchar* So when you add 1, it will move by 1 * sizeof(char) = 1 * 1 = 1 byte in memory. 因此,当您添加1时,它将在内存中移动1 * sizeof(char) = 1 * 1 = 1个字节。

printf("%d", *p);

You are printing as an int the location referenced by p . 您将作为int打印由p引用的位置。 So when you dereference p (by writing *p ) you are accessing the char (since p is of type char* ) referenced by p . 因此,当您取消引用 p (通过写*p )时,您正在访问由p引用的char (因为pchar*类型)。 Which is 00 . 这是00

If you wanted to print 3 instead of 0 you have to change your pointer type to int* instead of char* , making the pointer move by 1 * sizeof(int) = 1 * 4 = 4 bytes in memory. 如果要打印3而不是0 ,则必须将指针类型更改为int*而不是char* ,使指针在内存中移动1 * sizeof(int) = 1 * 4 = 4个字节。

The result you get will depend on the size of int on your implementation and its endianness. 获得的结果取决于实现中int的大小及其endianness。

Assuming 32bit ints, 8bit chars and a litte-endian environment (say x86), arr will be like this in memory: 假设32位整数,8位字符和一个litte-endian环境(比如x86), arr在内存中会是这样的:

<  arr[0]  > <  arr[1]  > <  arr[2] >
02 00 00 00  03 00 00 00  04 00 00 00
^  ^         ^
p  p+1 ...   p+4

If you take a char pointer to the start of that memory, and print out the first element, 2 should be output. 如果您使用char指针指向该内存的开头,并打印出第一个元素,则应输出2 If you increment that pointer, 0 will be output next. 如果递增该指针,则接下来将输出0。 You'll need to increment it a few times more to 'see' 3. 你需要将它增加几倍才能“看到”3。

Note that on a big-endian environment with the same type sizes, your program would have output two zeros, because the layout would have been: 请注意,在具有相同类型大小的大端环境中,您的程序将输出两个零,因为布局将是:

<  arr[0]  > <  arr[1]  > <  arr[2] >
00 00 00 02  00 00 00 03  00 00 00 04
^  ^         ^
p  p+1 ...   p+4

This is because of something called endianness . 这是因为称为字节序的东西。

When you create an array like int arr[3] = {2, 3, 4}; 当你创建一个类似int arr[3] = {2, 3, 4};的数组时int arr[3] = {2, 3, 4}; it gets created in the memory as follows 它在内存中创建如下

Big endian:
    0   1   2     3      4   5   6      7     8   9  10     11 
  +---+---+---+--------+---+---+---+--------+---+---+---+--------+
  |   |   |   | ..0010 |   |   |   | ..0011 |   |   |   | ..0100 |
  +---+---+---+--------+---+---+---+--------+---+---+---+--------+

  <--       2       --><--       3        --><--        4      -->

Little endian:
       0     1   2    3    4   5   6      7     8       9  10   11 
  +--------+---+---+---+---------+---+---+---+--------+---+---+---+
  | ..0010 |   |   |   |  ..0011 |   |   |   | ..0100 |   |   |   |
  +--------+---+---+---+---------+---+---+---+--------+---+---+---+

  <--       2       --><--       3        --><--        4      -->

To understand more, you need to modify you program as follows: 要了解更多信息,您需要按如下方式修改程序:

int main(void)
{

    int arr[3] = {2, 3, 4};
    char *p = (char*) arr;  
    int i;
    int size = (int)sizeof(arr);

    for (i=0; i<size ; i++) {
        printf("%d", *p);
        p++;
    }

    return 0;
}

And, to check the endianness of you hardware, you can use the following function. 并且,要检查硬件的字节顺序,可以使用以下功能。

void endian(void)
{
        int i = 1;

        if (*(char *) &i == 1)
                printf("Little endian \n");
        else
                printf("Big endian \n");

        return;
}

Here is a paste that will let you understand the issue better: http://codepad.org/ClrrwjKY 这是一个粘贴,可以让你更好地理解这个问题: http//codepad.org/ClrrwjKY

As you can see, the value of the consecutive integers appear separated by three zeroes. 如您所见,连续整数的值以三个零分隔。 This is because an integer is 4 bytes long, whereas a char is only 1 byte long. 这是因为整数长度为4个字节,而char只有1个字节长。 So when the int array is cast to char, you iterate over it byte by byte (or char by char), not by four bytes (int by int). 因此,当int数组转换为char时,您将逐字节(或char by char)迭代它,而不是四个字节(int by int)。

Here as 'p' is a character pointer.. p+1 increments the current value of p only by 1. As the array is integer, in order to access each values of the array one by one, you'll have to increment the character array by 2. If the address of integer array is 1000 therefore, 这里'p'是一个字符指针.. p + 1将p的当前值递增1.由于数组是整数,为了逐个访问数组的每个值,你必须增加字符数组由2.如果整数数组的地址是1000,

  arr[0] is at 1000
  arr[1] is at 1002
  arr[2] is at 1004

and the value of arr is the address of arr[0]; 而arr的值是arr [0]的地址; so initially 所以最初

 p=arr=1000

when p is incremented, p is 1001 whereas arr[1] is 1002 当p递增时,p为1001而arr [1]为1002

.. So in order to access all the values you'll have to increment the value of p twice each time.. ..因此,为了访问所有值,您必须每次增加p值两次..

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

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