深入理解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语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是 ...
随机推荐
- SpringBoot 整合 Sharding-JDBC 分库分表
导读 分库分表的技术有:数据库中间件Mycat(点我直达),当当网开源的Sharding-JDBC:我们公司用的也是sharding-jdbc,自己也搭建一个完整的项目,直接可以拿来用.下面附源码(C ...
- Oracle ROW_NUMBER() OVER()函数用法详解 (分组排序 例子多)
转载☞:https://blog.csdn.net/qq_25221835/article/details/82762416 ROW_NUMBER 语法 语法格式:row_number() over( ...
- 转载 | win11右键菜单改为win10的bat命令(以及恢复方法bat)
原文来自这里:https://blog.51cto.com/knifeedge/5340751 版权归:IT利刃出鞘 本质上就是写入注册表. 一.右键菜单改回Win10(展开) 1. 新建文件:win ...
- iOS开发基础109-网络安全
在iOS开发中,保障应用的网络安全是一个非常重要的环节.以下是一些常见的网络安全措施及对应的示例代码: Swift版 1. 使用HTTPS 确保所有的网络请求使用HTTPS协议,以加密数据传输,防止中 ...
- 小技巧:初始化后查看容器内某一bean的信息
1.debug 2. 3.与容器名对应,可以看到容器的对应信息 4.输入表达式可以直接获取对应结果信息,这里查看的是默认SpringSecurity过滤链的bean
- 记录一下实习的第一次线下面试的答辩经历,关于seata|sentinel,gateway与栈
面的一家小公司,他们准备做单体架构升级到微服务,所以问了我一些微服务相关的东西.回答的依托答辩,今天回想起来记录一下我造出来的笑话,正常的就不写在这里了. 首先我简历上大部分写的是熟悉,只有微服务写的 ...
- 新项目加入mybatisplus,我给自己挖了个坑 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 上述问题的解决办法:1首先看看@mapp ...
- WordPress基础之菜单导航栏设置
菜单是WordPress的一项重要功能,方便用户快速打开网站页面,我们通常说的网站导航栏就是菜单.菜单通常显示在网站的顶部或者底部,以Apple官网的为例: 这篇文章我们就学习下:如何添加.删除菜单: ...
- Qt+OpenCascade开发笔记(二):windows开发环境搭建(二):Qt引入occ库,搭建基础工程模板Demo和发布Demo
前言 Open CASCADE是由Open Cascade SAS公司开发和支持的开源软件开发平台,旨在为特定领域快速开发程序而设计.它是一个面向对象的C++类库,提供了丰富的几何造型.数据交换和 ...
- tcp udp测试
tcp udp测试 sub_udp.py #!/usr/bin/env python # -*- coding: utf-8 -*- # 可以正常接收udp import socket import ...