深入理解c语言指针与内存

一、将int强制转换为int指针,将int指针强转换为int

void f(void)
{
    int *p = (int*)100; //将int强制转换为int指针
    printf("%d\n",(int)p+1); //将int指针强转换为int, 然后+1
    printf("%d\n",(int)(p+1)); //将int指针加1(地址增加了4),强制转换为int
}

int main(int ac, char **av)
{
    f();
    return 0;
}

运行结果:

101
104

二、int指针转换为char指针

#include <stdio.h>

int main() {
    int a = 8;
    int* b = &a;
    int *c = (int*)((char*)b + 1);
    printf("b = %p, c = %p\n", b, c);
    *c  = 8;
    printf("%d\n", a);
    printf("b = %p, c = %p\n", b, c);
    printf("%d\n", *c);
    return 0;
}

 

运行结果:

b = 0061FEC4, c = 0061FEC5
2056
b = 0061FEC4, c = 0061FE00
1988445728

运行完第7行:整数a的地址为b = 0x61fec4,内存值为08000000;指针c指向0x61fec5,是a的第二个字节的地址。(小端存储)

运行完第8行,对c指向的内存赋值,这个四个字节被写为 08000000,因此a指向的内存被写为:00000808(b) = 2056(d)。

但由于存储c这个指针的内存正好因此被破坏了,被修改为0061FE00,因此此次输出*c的内容是未知的。

三、数组&指针

1. S6.828

#include <stdio.h>
#include <stdlib.h>

void f(void)
{
    int a[4];
    int *b = malloc(16);
    int *c;
    int i;


    printf("1: a = %p, b = %p, c = %p\n", a, b, c);

    c = a;
    for (i = 0; i < 4; i++)
        a[i] = 100 + i;
    c[0] = 200;
    printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
           a[0], a[1], a[2], a[3]);

    c[1] = 300;
    *(c + 2) = 301;
    3[c] = 302;  // 由于arr[2]等价于*(arr+2), 因而对于2[arr], 其实也就等价于*(2+arr)也是可以通过编译的, 因为+是满足交换律的。
    printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
           a[0], a[1], a[2], a[3]);

    c = c + 1;
    *c = 400;
    printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
           a[0], a[1], a[2], a[3]);

    c = (int *) ((char *) c + 1);
    *c = 500;
    printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
           a[0], a[1], a[2], a[3]);

    b = (int *) a + 1;
    c = (int *) ((char *) a + 1);
    printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}

int main(int ac, char **av)
{
    f();
    return 0;
}

运行结果:

1: a = 0061FEA0, b = 007515B8, c = 0000003D
2: a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103
3: a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
6: a = 0061FEA0, b = 0061FEA4, c = 0061FEA1

Process finished with exit code 0

2. 在 C/C++中,数组和指针是相互关联又有区别的两个概念。

  • 当我们声明一个数组时,其数组的名字也是一个指针,该指针指向数组的第一个元素。我们可以用一个指针来访问数组。data1是一个数组,sizeof(data1)是求数组的大小。

  • data2声明为指针,尽管它指向了数组data1的第一个数字,但它的本质仍然是一个指针。

  • 在C/C++中,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。

#include <stdio.h>
#include <stdlib.h>

int GetSize(int data[]){
	return sizeof(data);
}

int main(void) {

	int data1[] = {1,2,3,4,5};
	int size1 = sizeof(data1);
	int* data2 = data1;
	int size2 = sizeof(data2);
	int size3 = GetSize(data1);
	printf("%d %d %d %d\n", size1, size2, size3);
	return 0;
}

输出:

64位操作系统

20 8 8 8

四、函数返回局部指针?

  1. 以下代码IDE会告警:Address of stack memory associated with local variable 't' returned。由于局部变量的指针分配在栈上,且函数执行完,栈内存会自动释放,因此reverseLeftWords的返回值总是为NULL,不能得到正确的结果。
char* reverseLeftWords(char* s, int n){
    size_t sSize = strlen(s);
    if( n == 0 || n >= sSize) return s;
    char t[sSize+1];
    size_t i;
    for(i = 0; i < sSize; i++){
        t[i] = s[(i + n)% sSize];
    }
    t[i] = '\0';
    return t;
}
  1. 需要通过malloc来分配堆上内存,返回堆内存地址。
char* reverseLeftWords(char* s, int n){
    size_t sSize = strlen(s);
    if( n == 0 || n >= sSize) return s;
    char* t = (char*)malloc(sizeof(char*)*(sSize+1));

    size_t i;
    for(i = 0; i < sSize; i++){
        t[i] = s[(i + n)% sSize];
    }
    t[i] = '\0';
    return t;
}

posted on 2022-01-05 23:28  七昂的技术之旅  阅读(213)  评论(0编辑  收藏  举报

导航