深入理解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
四、函数返回局部指针?
- 以下代码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;
}
- 需要通过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语言指针与内存的更多相关文章
- 2-Linux C语言指针与内存-学习笔记
Linux C语言指针与内存 前面我们对于: c语言的基本用法 makeFile文件的使用 main函数的详解 标准输入输出流以及错误流管道 工具与原理 指针与内存都是c语言中的要点与难点 指针 数组 ...
- 深入理解C语言 - 指针使用的常见错误
在C语言中,指针的重要性不言而喻,但在很多时候指针又被认为是一把双刃剑.一方面,指针是构建数据结构和操作内存的精确而高效的工具.另一方面,它们又很容易误用,从而产生不可预知的软件bug.下面总结一下指 ...
- "深入理解C语言" 指针
本文对coolshell中的"深入理解C语言"这篇文章中提到的指针问题, 进行简要的分析. #include <stdio.h> int main(void){ ]; ...
- 深入理解C语言 - 指针详解
一.什么是指针 C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址.CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位.这里,数据对象是指存储在 ...
- 小强版之无码理解C语言指针
1. 先从普通变量开始 2. 撸完变量撸指针 3. 故事情节进一步发展,此处少儿不宜 4. 奶茶妹妹捉奸,小强死定了 5. 源码欣赏 #include <stdio.h> ...
- 13深入理解C指针之---内存管理
该系列文章源于<深入理解C指针>的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教. 内存管理对所有程序都很重要,主要包括显式内存管理和隐式内存管理.其中隐式内存管理主要是 ...
- 这样子来理解C语言中指针的指针
友情提示:阅读本文前,请先参考我的之前的文章<从四个属性的角度来理解C语言的指针也许会更好理解>,若已阅读,请继续往下看. 我从4个属性的角度来总结了C语言中的指针概念.对于C语言的一个指 ...
- windev中的内存机制及其与C语言中的内存指针相似性(一)
windev中的内存机制,是初入windev世界必须要越过的一道高山,以下我的理解和经验未必都对,如有错误或遗漏,以后再纠正或补充!另外,以下内容,咱先谈应用,再说对机制的认识和理解. 一.新建表单, ...
- C 语言中的指针和内存泄漏
引言对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧 ...
- C语言中的指针和内存泄漏
引言 对于任何使用C语言的人,如果问他们C语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是 ...
随机推荐
- Java FastJson解析json字符串
json转map Map<String, 实体类> titleMap=JSON.parseObject(JSON字符串, new TypeReference<HashMap<S ...
- SpringMVC面试题及答案
SpringMvc 的控制器是不是单例模式,如果是,有什么问题,怎么解决? 问题:单例模式,在多线程访问时有线程安全问题 解决方法:不要用同步,在控制器里面不能写字段 SpringMvc 中控制器的注 ...
- NSSCTF———Web(sql注入)
[LitCTF 2023]这是什么?SQL !注一下 ! [SWPUCTF 2022 新生赛]ez_sql [GXYCTF 2019]BabySqli 点击右下角文章可跳转 [LitCTF 2023] ...
- Linux安全启动及Machine Owner Key(UEFI BIOS MBR GPT GRUB)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明 无 前言 只要装过各种系统的人都或多或少会接触 ...
- Odoo 自定义form表单按钮点击事件处理程序
实践环境 Odoo 14.0-20221212 (Community Edition) 代码实现 方案1 通过研究发现,点击odoo form表单按钮时,会调用odoo14\odoo\addons\w ...
- 搭建lnmp环境-mysql(第五步)
版本mysql 5.7 先删除系统自带的db 新建文件夹/data/download 进入后下载 wget http://repo.mysql.com/mysql57-community-releas ...
- python的Faker使用
import json from faker import Faker from faker_demo.CustomFaker import CustomProvider myfaker = Fake ...
- 【Java】【常用类】Date 日期类
java.util.Date java.sql.Date 创建日期对象和打印结果 public class DateTest { public static void main(String[] ar ...
- 【Zookeeper】Re01 安装与操作
Zookeeper基于JDK开发出来的 运行环境至少需要JRE 快速安装JDK: yum install -y java-1.8.0-openjdk-devel.x86_64 # ZK镜像仓库 htt ...
- PyTorch视觉模型库torchvision.models介绍
安装pytorch时我们一般都是会一并选择安装自带的视觉模型库 torchvision , 该库不仅有经典的视觉模型结构同时还提供了对应参数的下载功能,可以说torchvision库是十分方便于研究 ...