一、将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;
}

深入理解c语言指针与内存的更多相关文章

  1. 2-Linux C语言指针与内存-学习笔记

    Linux C语言指针与内存 前面我们对于: c语言的基本用法 makeFile文件的使用 main函数的详解 标准输入输出流以及错误流管道 工具与原理 指针与内存都是c语言中的要点与难点 指针 数组 ...

  2. 深入理解C语言 - 指针使用的常见错误

    在C语言中,指针的重要性不言而喻,但在很多时候指针又被认为是一把双刃剑.一方面,指针是构建数据结构和操作内存的精确而高效的工具.另一方面,它们又很容易误用,从而产生不可预知的软件bug.下面总结一下指 ...

  3. "深入理解C语言" 指针

    本文对coolshell中的"深入理解C语言"这篇文章中提到的指针问题, 进行简要的分析. #include <stdio.h> int main(void){ ]; ...

  4. 深入理解C语言 - 指针详解

    一.什么是指针 C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址.CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位.这里,数据对象是指存储在 ...

  5. 小强版之无码理解C语言指针

     1. 先从普通变量开始   2. 撸完变量撸指针   3. 故事情节进一步发展,此处少儿不宜   4. 奶茶妹妹捉奸,小强死定了   5. 源码欣赏  #include <stdio.h> ...

  6. 13深入理解C指针之---内存管理

    该系列文章源于<深入理解C指针>的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教. 内存管理对所有程序都很重要,主要包括显式内存管理和隐式内存管理.其中隐式内存管理主要是 ...

  7. 这样子来理解C语言中指针的指针

    友情提示:阅读本文前,请先参考我的之前的文章<从四个属性的角度来理解C语言的指针也许会更好理解>,若已阅读,请继续往下看. 我从4个属性的角度来总结了C语言中的指针概念.对于C语言的一个指 ...

  8. windev中的内存机制及其与C语言中的内存指针相似性(一)

    windev中的内存机制,是初入windev世界必须要越过的一道高山,以下我的理解和经验未必都对,如有错误或遗漏,以后再纠正或补充!另外,以下内容,咱先谈应用,再说对机制的认识和理解. 一.新建表单, ...

  9. C 语言中的指针和内存泄漏

    引言对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧 ...

  10. C语言中的指针和内存泄漏

    引言 对于任何使用C语言的人,如果问他们C语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是 ...

随机推荐

  1. Java FastJson解析json字符串

    json转map Map<String, 实体类> titleMap=JSON.parseObject(JSON字符串, new TypeReference<HashMap<S ...

  2. SpringMVC面试题及答案

    SpringMvc 的控制器是不是单例模式,如果是,有什么问题,怎么解决? 问题:单例模式,在多线程访问时有线程安全问题 解决方法:不要用同步,在控制器里面不能写字段 SpringMvc 中控制器的注 ...

  3. NSSCTF———Web(sql注入)

    [LitCTF 2023]这是什么?SQL !注一下 ! [SWPUCTF 2022 新生赛]ez_sql [GXYCTF 2019]BabySqli 点击右下角文章可跳转 [LitCTF 2023] ...

  4. Linux安全启动及Machine Owner Key(UEFI BIOS MBR GPT GRUB)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   无 前言   只要装过各种系统的人都或多或少会接触 ...

  5. Odoo 自定义form表单按钮点击事件处理程序

    实践环境 Odoo 14.0-20221212 (Community Edition) 代码实现 方案1 通过研究发现,点击odoo form表单按钮时,会调用odoo14\odoo\addons\w ...

  6. 搭建lnmp环境-mysql(第五步)

    版本mysql 5.7 先删除系统自带的db 新建文件夹/data/download 进入后下载 wget http://repo.mysql.com/mysql57-community-releas ...

  7. python的Faker使用

    import json from faker import Faker from faker_demo.CustomFaker import CustomProvider myfaker = Fake ...

  8. 【Java】【常用类】Date 日期类

    java.util.Date java.sql.Date 创建日期对象和打印结果 public class DateTest { public static void main(String[] ar ...

  9. 【Zookeeper】Re01 安装与操作

    Zookeeper基于JDK开发出来的 运行环境至少需要JRE 快速安装JDK: yum install -y java-1.8.0-openjdk-devel.x86_64 # ZK镜像仓库 htt ...

  10. PyTorch视觉模型库torchvision.models介绍

    安装pytorch时我们一般都是会一并选择安装自带的视觉模型库 torchvision ,  该库不仅有经典的视觉模型结构同时还提供了对应参数的下载功能,可以说torchvision库是十分方便于研究 ...