深入了解指针(5)

一.sizeof和strlen的对比

1.sizeof

sizeof是操作符,不是函数!!!
计算的是类型,变量和表达式所占用内存的大小,单位是字节不关注内存里放的是什么内容,且当sizeof里放的是表达式的时候,表达式不计算。

int main(){
int a=10;
printf("%zd\n",sizeof(a));
printf("%zd\n",sizeof(int));//计算类型大小时,必须加(),变量和表达式可以不加。
printf("%zd\n",sizeof a);//验证了sizeof不是函数。
return 0;
}

2.strlen

而strlen是库函数,计算的是字符串的长度。他的头文件是<string.h>,参数是一个指针变量,统计的是从这个指针所指的位置到\0为主的字符个数,会关注内存中有没有\0,没有就会向后访问,可能会越界。

size_t strlen(const char* p);//函数原型
#include <string.h>
int main() {
	char arr1[3] = { 'a','b','c' };
	char arr2[] = "abc";
	printf("%zd\n", sizeof(arr1));//3
	printf("%zd\n", sizeof(arr2));//4
	printf("%zd\n", strlen(arr1));//不确定
	printf("%zd\n", strlen(arr2));//3
	return 0;

}

二.数组和指针相关题目

1.一位数组

int main(){
	int a[] = { 1,2,3,4 };
	printf("%zd\n", sizeof(a));//a是数组名,sizeof计算的是整个数组的大小,单位是字节,-16
	printf("%zd\n", sizeof(a + 0));//a没有单独放在sizeof()里面,是数组首元素的地址,加0还是地址,大小是4/8.
	printf("%zd\n", sizeof(*a));//*a是数组首元素  -4
	printf("%zd\n", sizeof(a + 1));//a+1是数组第二个元素的地址 -4/8
    printf("%zd\n", sizeof(a[1]));//第二个元素  -4
    printf("%zd\n", sizeof(&a));//&a取出整个数组的地址 -4/8
	printf("%zd\n", sizeof(*&a));//*和&相互抵消,计算的是整个数组的大小 -16
	printf("%zd\n", sizeof(&a + 1));//整个数组的地址加1还是地址  -4/8
	printf("%zd\n", sizeof(&a[0])); //第一个元素的地址  -4/8
	printf("%zd\n", sizeof(&a[0] + 1));//第二个元素的地址  -4/8

	return 0;
}

2.字符数组

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//arr是数组名,计算的是整个数组的大小,-6
	printf("%d\n", sizeof(arr + 0));//arr没有单独放在sizeof里,是数组首元素的地址-4/8
	printf("%d\n", sizeof(*arr));//第一个元素 -1
	printf("%d\n", sizeof(arr[1]));//第二个元素 -1
	printf("%d\n", sizeof(&arr));//整个数组的地址 4/8 
	printf("%d\n", sizeof(&arr + 1));//整个数组之后的地址 4/8
	printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址 4/8

	return 0;
}
#include <string.h>

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//数组中没有\0,不确定在后面的内存什么时候出现 
	printf("%d\n", strlen(arr + 0));//首元素的地址开始找\0
	printf("%d\n", strlen(*arr));//参数是'a',ascll值是97,传递的可能是野指针
	//这是错误的代码,传给他的应该是个指针变量
	printf("%d\n", strlen(arr[1]));//传递的'b',98,同理,error
	printf("%d\n", strlen(&arr));//从整个数组的地址开始也不确定\0的位置  x
	printf("%d\n", strlen(&arr + 1));//同理,从数组后的指针开始也不确定  x-6
	printf("%d\n", strlen(&arr[0] + 1));//第二个元素的地址开始  x-1

	return 0;
}


int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//整个数组长度  7
	printf("%d\n", sizeof(arr + 0));//第一个元素的地址  4/8
	printf("%d\n", sizeof(*arr));//首元素   1
	printf("%d\n", sizeof(arr[1]));//第二个元素  1
	printf("%d\n", sizeof(&arr));//整个数组的地址 4/8
	printf("%d\n", sizeof(&arr + 1));//数组之后的地址  4/8
	printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址  4/8

	return 0;
}

#include <string.h>

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//整个数组的长度  6
	printf("%d\n", strlen(arr + 0));//首元素的地址  6
	printf("%d\n", strlen(*arr));//首元素  97 error
	printf("%d\n", strlen(arr[1]));//第二个元素 98 error,野指针
	printf("%d\n", strlen(&arr));//整个数组的地址 6

	printf("%d\n", strlen(&arr + 1));//数组之后的地址开始 不确定
	printf("%d\n", strlen(&arr[0] + 1));//第二个元素的地址 5

	return 0;
}
int main()
{
	const char * p = "abcdef";

	printf("%d\n", sizeof(p));//p是'a'的地址,4/8
	printf("%d\n", sizeof(p + 1));//'b'的地址 4/8
	printf("%d\n", sizeof(*p));//'a'  1
	printf("%d\n", sizeof(p[0]));//1
	
	printf("%d\n", sizeof(&p));//二级指针,指向的是p  4/8
	printf("%d\n", sizeof(&p + 1));//4/8
	printf("%d\n", sizeof(&p[0] + 1));//第二个元素地址 4/8

	return 0;
}
int main()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	printf("%d\n", strlen(*p));//error
	printf("%d\n", strlen(p[0]));//error
	printf("%d\n", strlen(&p));//从二级指针开始计数,不确定到\0的个数,二级指针指向的空间与p指向的无关
	printf("%d\n", strlen(&p + 1));//不确定

	printf("%d\n", strlen(&p[0] + 1));//'b'的地址   5

	return 0;
}

3.二维数组

int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//整个数组的大小 48
	printf("%d\n", sizeof(a[0][0]));//4
	printf("%d\n", sizeof(a[0]));//a[0]是第一行数组的名字,计算的是第一行数组的大小 16
	printf("%d\n", sizeof(a[0] + 1));//第1行第二个元素的地址  4/8

	printf("%d\n", sizeof(*(a[0] + 1)));//第二个元素  4
	printf("%d\n", sizeof(a + 1));//第二行的地址  4/8

	printf("%d\n", sizeof(*(a + 1)));//第二行的大小 16
	printf("%d\n", sizeof(&a[0] + 1));//第二行的地址  4/8
	printf("%d\n", sizeof(*(&a[0] + 1)));//第二行的大小 16
	printf("%d\n", sizeof(*a));//第一行大小  16
	printf("%d\n", sizeof(a[3]));//第4行的大小  16
	return 0;
}

三、指针运算题

#include <stdio.h>

int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int* ptr = (int*)(&a + 1);//取出整个数组的地址然后加1还是数组指针,指向a数组后面的位置,强制类型转换成整型指针赋给ptr,减1解引用后就是5
    printf("%d,%d", *(a + 1), *(ptr - 1));//2,5
    return 0;//首元素地址加一指向第二个元素,解引用是2.
}



在X86(32位)环境下
假设结构体的大小是20个字节
程序输出的结果是啥?
struct Test
{
    int Num;
    char* pcName;
    short sDate;
    char cha[2];
    short sBa[4];
} * p = (struct Test*)0x100000;
//结构体指针变量p,用一个被强制类型转换的数值初始化
int main()
{
    printf("%p\n", p + 0x1);//0x1就是1,指针加1看他的类型,那么就跳过一个结构体类型,20个字节,一个字节有一个地址,那就是0x100020吗?不是的,应该先转化成16进制的,是0x100014.用指针打印就是00100014
    printf("%p\n", (unsigned long)p + 0x1);//将p强转为一个数字,加1就是真的加1,答案是0x100001,打印出来就是00100001
    printf("%p\n", (unsigned int*)p + 0x1);
//将p强转为整型指针,加1就跳过4个字节,打印为地址就是00100004.
    return 0;
}



#include <stdio.h>

int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };//初始化应该也用{},但现在里面相当于括号表达式,从最左边的表达式依次开始计算,结果是最后一个表达式的结果。这里是
    {1,35,00,0}int* p;
    p = a[0];//p是第一行的地址
    printf("%d", p[0]);这里是第一行第一个元素 1
    return 0;
}

int main()
{
    int a[5][5];

    int (*p)[4];

    p = a;

    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    //随下标增大,地址也逐渐增大,用%d打印是-4,在内存中以二进制补码表示     原码 10000000000000000000000000000100
              //反码 11111111111111111111111111111011
              //补码 11111111111111111111111111111100    
              //补码直接被当做以地址打印出来就是16进制的fffffffc
    return 0;
}

在这里插入图片描述

#include <stdio.h>
int main()
{
    int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    int* ptr1 = (int*)(&aa + 1);//指向的是10后面的地址,被强转为整型指针,后面操作减1就指向10的空间

    int* ptr2 = (int*)(*(aa + 1));//指的是第二行首元素的地址

    printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10和5

    return 0;
}
#include <stdio.h>

int main()
{
    char* a[] = { "work","at","alibaba" };
    char** pa = a;
    pa++;
    printf("%s\n", *pa);//at
    return 0;
}

在这里插入图片描述

#include <stdio.h>
int main()
{
    char* c[] = { "ENTER","NEW","POINT","FIRST" };
    char** cp[] = { c + 3,c + 2,c + 1,c };
    char*** cpp = cp;

    printf("%s\n", **++cpp);//POINT
    printf("%s\n", *-- * ++cpp + 3);//ER
    printf("%s\n", *cpp[-2] + 3);//ST
    printf("%s\n", cpp[-1][-1] + 1);//EW
    return 0;
}

在这里插入图片描述

Matlab基于粒子群优化算法及鲁棒MPPT控制器提高光伏并网的效率内容概要:本文围绕Matlab在电力系统优化与控制领域的应用展开,重点介绍了基于粒子群优化算法(PSO)和鲁棒MPPT控制器提升光伏并网效率的技术方案。通过Matlab代码实现,结合智能优化算法与先进控制策略,对光伏发电系统的最大功率点跟踪进行优化,有效提高了系统在不同光照条件下的能量转换效率和并网稳定性。同时,文档还涵盖了多种电力系统应用场景,如微电网调度、储能配置、鲁棒控制等,展示了Matlab在科研复现与工程仿真中的强大能力。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的高校研究生、科研人员及从事新能源系统开发的工程师;尤其适合关注光伏并网技术、智能优化算法应用与MPPT控制策略研究的专业人士。; 使用场景及目标:①利用粒子群算法优化光伏系统MPPT控制器参数,提升动态响应速度与稳态精度;②研究鲁棒控制策略在光伏并网系统中的抗干扰能力;③复现已发表的高水平论文(如EI、SCI)中的仿真案例,支撑科研项目与学术写作。; 阅读建议:建议结合文中提供的Matlab代码与Simulink模型进行实践操作,重点关注算法实现细节与系统参数设置,同时参考链接中的完整资源下载以获取更多复现实例,加深对优化算法与控制系统设计的理解。
指针是C语言中非常强大但又容易出错的特性之一。深入了解指针有助于编写高效、灵活的代码,也能帮助我们更好地理解底层内存操作。 ### 一、指针的基本概念 指针是一个变量,其值为另一个变量的地址。在C语言中,每个变量都有一个内存地址,我们可以使用 `&` 运算符获取变量的地址,并使用 `*` 运算符声明指针和访问指针所指向的值。 ```c int a = 10; int *p = &a; // p 是指向 int 的指针,保存了 a 的地址 printf("a 的值: %d\n", *p); // 通过指针访问 a 的值 ``` ### 二、指针的本质 指针的本质是一个地址。在内存中,每一个字节都有一个唯一的地址编号(内存地址)。指针变量中存储的是某个变量在内存中的起始地址。 ### 三、指针的类型 指针是有类型的,比如 `int*`、`char*`、`float*` 等。指针类型决定了指针所指向的数据类型,也决定了指针在进行加减运算时的步长。 ```c int arr[3] = {1, 2, 3}; int *p = arr; p++; // 指针移动的步长是 sizeof(int),通常是4字节 ``` ### 四、指针与数组的关系 数组名在大多数情况下会被视为指向数组第一个元素的指针。数组和指针可以互换使用,但数组名是常量指针,不能进行赋值。 ```c int arr[] = {1, 2, 3}; int *p = arr; for(int i = 0; i < 3; i++) { printf("%d ", *(p + i)); } ``` ### 五、指针与函数 指针可以作为函数参数,实现对实参的修改;也可以作为函数返回值,返回一个地址。 ```c void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } int main() { int x = 5, y = 10; swap(&x, &y); printf("x = %d, y = %d\n", x, y); // 输出 x = 10, y = 5 return 0; } ``` ### 六、指针与动态内存分配 使用 `malloc`、`calloc`、`realloc` 和 `free` 可以在堆上动态分配内存,返回的是一个指针。 ```c int *arr = (int *)malloc(5 * sizeof(int)); if(arr != NULL) { for(int i = 0; i < 5; i++) { arr[i] = i + 1; } free(arr); // 释放内存 } ``` ### 七、野指针与空指针 - **野指针**:指向不确定地址的指针,未初始化或指向已被释放的内存。 - **空指针**:值为 NULL 的指针,表示不指向任何地方。 ```c int *p = NULL; // 空指针 int *q; // 野指针 ``` 使用前应始终检查指针是否为 NULL。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值