发布于: -/最后更新: -/5 分钟/

Suryanarayana C Pointer 笔记

摘要

指针是C和C++编程中的一个基本概念。指针是一种变量,它存储了另一个变量的内存地址。通过指针,可以间接访问和操作变量的值。指针的声明通常使用星号(*)符号,例如`int *p;`,这声明了一个指向整数的指针`p`。 指针可以用于动态内存分配,函数参数传递,返回多个值等场景。指针运算包括指针的加减法、比较等。指针也可以作为函数参数,允许函数修改外部变量的值。 此外,指针还可以用于实现函数指针,函数指针是指向函数的指针,可以用来调用函数。函数指针的声明通常使用括号和星号,例如`void (*fp)(int, char);`,这声明了一个指向函数的指针`fp`,该函数的返回类型为`void`,参数类型为`int`和`char`。 在内存管理中,指针也扮演着重要的角色。堆栈(Stack)和

视频入口: https://www.bilibili.com/video/BV1bo4y1Z7xf

Initialization

<data type> *<variable name>;: The pointer to the <data type> of <variable name>

& (ampersand)

&<variable>: Return the address of the variable

* (asterisk)

*<variable>: Return the value at variable's address
To access the address of the variable in format

The asterisk meaning between int* p and *p are not the same.

int* is a type that a pointer point to a data of int type.

*p is to dereference the address which stored in variable p.

Pointer arithmetic

c++
int a = 1024;
int *p;
p = &a;  // Assume variable `a` 's address is 2077 
cout << p << endl;  // 2077 in decimal
cout << p + 1 << endl; // 2081 in decimal
c++
int a = 1025;
int* p;
p = &a;
printf("Address=%d; value=%d\n", p, *p);

char* p0;  // 1 char: 1 byte = 8 bit
p0 = (char*)&a;  // Cast int* to char*

// 1025 in memory (small-endian order):
// ... 00000000     00000000    00000100    00000001 ...
// ...(p + 3) ^    (p + 2) ^   (p + 1) ^   (p + 0) ^ ...
// '^' means toward bit
printf("%d\n", (int)*p0);  // 0000100 => 1
printf("%d\n", (int)*(p0 + 1)); // 00000001 => 4

Void Pointer - Generic Pointer

void* <variable name>;

It can't be used to print the value that it points.

It can be used to print itself address.

Char Array

char c[] = "ABC";: It will be stored in the space for array (Stack).

const char* c = "Hello";: It will be stored as compile time constant, so it cannot be modified (Like: c[0] = 'a')

Array & Pointer

The relationship between Array & Pointer.

arr[x] <==> *(arr+x)

(You need to know that arr is a const variable, so it cannot be assigned (Like: arr = var)

It just the same as the relationship between Reference & Pointer

int &a = var <==> int* const a = &var

return a <==> return *a

The array in function parameters

c++
// ...
int get_size(int arr[])
{
    return sizeof(arr) / sizeof(arr[0])       
}

Most of the time, return result is 1 (Depend on the platfrom)

Because the declaration of int arr[] is actually a int pointer which points to the first address of the array.

Compiler translates int arr[] => int* arr

So the variable of arr 's size is the size of pointer.

The purpose is to reduce the time and space cost.(It don't need to copy the array)

mulit-dimensional array

2-dimensional array:

a[i][j] => *(a[i]+j) => *(*(a+i)+j)

a's type: int (*)[]

a[i]'s type: int*

3-dimensional array:

a[i][j][k] => *(a[i][j] + k) => *(*(a[i] + j ) + k ) => *(*(*(a + i) + j ) + k

a's type: int(*)[][]

a[i]'s type: int(*)[]

a[i][j]'s type: int*

Diffence between array type and pointer type

Yes! They are not the same type.
You can't consider them as the same type!

C++
int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int (*p)[3] = arr;
printf("%d\n", p);
printf("%d\n", *p);

This circumstance only happens in static creation!

p and *p's output are both equal

Differences:

p: It's a one-dimensional pointer;

*p: It's a int* pointer.

Explanation

type of array inequals to pointer

In the other word, array is a special pointer.

What is the point of defining this?

  1. It's a fake-pointer (pointer's address = the address it's point to)
    Because the static array is continuous.
    But dynamic multi-dimension array is not continuous from row to row.

  2. It needs each row's capacity.
    For example:
    sizeof(int[3]) = 12
    As we all know, sizeof(int) * 3 = 12 bytes
    So when you do operator like +, C can know plus 1 equal to how many bytes

Much deeper understanding

Static:

C++
int arr[3][3];
for (int y = 0; y < 3; y++)
{
    for (int x = 0; x < 3; x++)
    {
        // These following three are all equivalent
        *(arr[y]+x) = 3 * y + x;
        *(*(arr + y) + x) = 3 * y + x;
        *((*arr + 3 * y) + x) = 3 * y + x;  // Important!
      }
}
int (*p)[3] = arr;
// All equal
printf("%d\n", p);
printf("%d\n", *p);

pic
点击查看大图
pic
C++
int b[3][1];
int (*p)[1] = b;
// int **p = b;  // Syntax Error

Dynamic:

C++
int **arr = (int **)calloc(3, sizeof(int *));
for (int y = 0; y < 3; y++)
{
    *(arr + y) = (int *)calloc(3, sizeof(int));
    for (int x = 0; x < 3; x++)
    {
      // ...
    }
}
int** p = arr;
// Not equal
printf("%d\n", p);
printf("%d\n", *p);

It doesn't need [] type for helping.

Because it's structure is different from static array.

It's discontinuous, and is similar to deque in STL:

pic
点击查看大图
pic

一段一段的连续空间's beginning address are different.

StackVsHeap
点击查看大图
StackVsHeap

Data in memory

High Bit & Low Bit

注意高字节在左边,低字节在右边

plain
1           1           1           1

High Bit                          Low Bit

Byte Order(Endian): Big Endian(大端) & Small Endian(小端)

这地方我觉得杨老师在哪一节课上提到过 unix模式 与 微软模式

大概就是 大端 与 小端 序

windows是小端序,unix我就不清楚了

0b1001111

Big Endian

plain
Low address in mem -------------> High address in mem

1   0   0   1   1   1   1

High Bit <----------------------- Low Bit

BigEndian
点击查看大图
BigEndian

Small Endian

plain
Low address in mem -------------> High address in mem
1   1   1   1   0   0   1
Low Bit <------------------------ High Bit

SmallEndian
点击查看大图
SmallEndian

Pasted image 20260114224816.png
点击查看大图
Pasted image 20260114224816.png
Pasted image 20260114224816.png
点击查看大图
Pasted image 20260114224816.png

LSB (Least Significant Bit): 最低有效位

0b10010101

The bold underlined bit above called Least Significant Bit

  • Big Endian: In Big Endian systems, the most significant byte (MSB) is stored at the smallest memory address. So, the most significant byte comes first in memory.

  • Little Endian: In Little Endian systems, the least significant byte (LSB) is stored at the smallest memory address. So, the least significant byte comes first in memory.

正文结束