C语言深度剖析读书笔记(一)

本文深入探讨了C语言中的指针概念及其应用,详细解释了如何通过指针访问和操作内存,包括指针的基本操作、函数指针的使用、以及不同类型的指针变量特性。同时,文中还涉及了内存区域的划分与使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include<stdlib.h>
int main()
{
           int a[5] = { 1, 2, 3, 4, 5 };
           int* ptr1 = (int *)(&a + 1);
           int* ptr2 = (int *)((int)a + 1);
          printf( "%x,%x", ptr1[-1], *ptr2);
           //ptr1 &a 得到数组首元素地址,+1 ->元素5后面,-1得到5
           // a->得到a的地址,转换为int型后,得到4651752,+1->4651753,
           //转换为int* 后,得到33554432(我也不知道为什么) 再转为十六进制输出可得
          system( "pause");
           return 0;
}

#define _CRT_SECURE_NO_WARNINGS 1


#include<stdio.h>
#include<stdlib.h>
int checkSystem()
{
           union check
          {
           int i;
           char ch;
} c;
          c.i = 1;
           return(c.ch == 1);
}
int main()
{
           //void* p;
           //p++;
           //p += 1; 
           //未知大小  引深为不知道内存目的地址的确切值

           //int* pint=NULL;
           //pint++; //ANSI:正确
           //printf("%d\n", pint);

           //void* memcpy(void* dest, const void *src, size_t len);
           //void* memset(void* buffer, int c, size_t num);

           //int IntArray_a[100];
           //memset(IntArray_a, 0, 100 * sizeof(int)); //将 IntArray_a 清 0
           //for (int i = 0; i < 100; i++)
           //{
           //       printf("%d ", IntArray_a[i]);
           //}

           //void 不能代表一个真实的变量,因为在定义变量时,要为变量分配一定的空间,但是
           //void型,不能知道它的数据类型大小

           /*char * Func(void)
          {
                   char str[30];
                   …
                   return str;
          }
*/
           //str位于栈内存中,在出了作用域后,便被释放。

           //return ;什么也不做,什么也不返回
           //const 修饰的是只读变量 具有不可变性
           //const 修饰的只读变量必须在定义的同时初始化,因为具有不可变性,如果没有在初始化
           //的时候进行初始化,那么在后面点操作中,便不能修改它的值。

           /*int i = 0;
          const c = 3;
          scanf("%d", &i);
          switch (i)
          {
          case 1:
                   ;
                   break;
          case 2:
                   break;
          case  c:
                   break;
          }*/
           //case 后面只能是常量值,不能是const修饰的只读变量
           /*const 定义的只读变量从汇编的角度来看, 只是给出了对应的内存地址, 而不是象#define
          一样给出的是立即数,所以,const 定义的只读变量在程序运行过程中只有一份拷贝(因为
          它是全局的只读变量,存放在静态区) ,而#define 定义的宏常量在内存中有若干个拷贝。
          #define 宏是在预编译阶段进行替换,而 const 修饰的只读变量是在编译的时候确定其值。
          #define 宏没有类型,而 const 修饰的只读变量具有特定的类型。*/

           /*const 修饰一般变量时,放在签名和后面都没有关系
          int const i = 2; 或 const int i = 2;*/

           //int a = 1;
           //int b = 2;
           //const int *p=a; // p 可变,p 指向的对象不可变
           ////p = b;
           //printf("%d\n", p);

           //int const *p; // p 可变,p 指向的对象不可变
           //int *const p; // p 不可变,p 指向的对象可变
           //const int * const p; //指针 p 和 p 指向的对象都不可变

           //struct 的成员默认情况下属性是 public 的,而 class 成员却是 private 的。
           /*int ret=checkSystem();
          printf("%d\n", ret);*/
          system( "pause");
           return 0;
}


#include <stdio.h>
#include<stdlib.h>
int main()
{
           int a[5] = { 1, 2, 3, 4, 5 };
           int* ptr1 = (int *)(&a + 1);
           int* ptr2 = (int *)((int)a + 1);
          printf( "%x,%x", ptr1[-1], *ptr2);
           //ptr1 &a 得到数组首元素地址,+1 ->元素5后面,-1得到5
           // a->得到a的地址,转换为int型后,得到4651752,+1->4651753,
           //转换为int* 后,得到33554432(我也不知道为什么) 再转为十六进制输出可得
          system( "pause");
           return 0;
}



#include<iostream>
using namespace std;
int main()
{
           //编译器的确会将注释剔除,但不是简单的剔除,而是用空格代替原来的注释
           //C 语言里以反斜杠(\)表示断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符
           //自动接续到前一行。但是注意:反斜杠之后不能有空格,反斜杠的下一行之前也不能有空格。

           //左移不管有没有符号位,全部补零
           //右移时,符号位随同移动,为正时,补0,负数时 补1
          system( "pause");
           return 0;
}



一维数组做参数时,将一维数组解析为指向数组首元素地址的指针,

char* (*fun1)(char* p1, char* p2);  函数指针,指向一个函数的指针
例:

#include <stdio.h>
#include<stdlib.h>
#include <string.h>
char* fun(char * p1, char* p2)
{
           int i = 0;
          i = strcmp( p1, p2 );
           if (0 == i)
          {
                    return p1 ;
          }
           else
          {
                    return p2 ;
          }
}
int main()
{
           char* (*pf)(char * p1, char* p2);
          pf = &fun; //pf = fun;  //也是可以的,因为函数名在编译时,其实就是个地址
           //创建一个函数指针pf,pf指向fun,(*pf)("aa", "bb")调用函数
          (*pf)( "aa", "bb" );
          system( "pause");
           return 0;
}


#include<stdio.h>
#include<stdlib.h>
void Function()
{
          printf( "Call Function!\n");
}
int main()
{
           //void(*p)()定义一个指针p 参数列表和返回值全为空,&p求指针变量p的地址,强转为int*
           //类型,表示将地址强制转换成指向 int 类型数据的指针,,Function为函数的首地址,
           //多以这段代码的意思是,将函数Function的入口地址强制强转为int类型后,在赋值给
           //指针变量p
           void(*p)();
          *( int*)&p = (int )Function;
          (*p)();
          system( "pause");
           return 0;
}


(*(void(*)())0)()分析
1.void(*)()  是一个函数指针,函数列表为空,返回值为空,
2.void(*)() 0 ,将0转换为一个函数类型的指针,0是一个地址,将函数存放在首地址为0的地方
3.(*(void(*)())0) ,将首地址0中的内容取出来,
4.(*(void(*)())0)() ,函数调用

静态区: 保存自动全局变量和static变量(包括static全局和static局部),静态区的内容在整个生命周期都存在,内容有编译器在编译的时候分配,只初始化一次,
栈: 保存局部变量,栈上的内容只在函数范围内存在,当出了函数的作用域时,会被自动销毁,特点:效率高,空间大小有限
堆:有malloc/new 分配空间,有free/delete释放,注意配对使用,容易出错。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值