目录
断言(assert)
assert是一个宏,用于在运行时(当程序正在执行时)确保程序符号指定条件,如果不符合,就会报错终止运行,在使用宏assert()时,要在程序中包含assert.h的头文件。
#include <stdio.h>
#include<assert.h>
//#define NDEBUG//加上即使为假也不产生任何作用,移除assert这个指令
int main()
{
int a = 10;
int* p = &a;
//...
//...
p = NULL;
//if (p != NULL)
//{
// //...
//}
assert(p != NULL);//如果为假,直接报错
//如果为真,不会产生任何影响
printf("%d\n", *p);
}
如果assert()的语句为假:直接报错,且显示错误的行数;
为真:不产生任何影响;
当我们不想使用assert()时,可以直接加一个宏NDEBUG,它会移除assert这个指令;
一般在Debug中使用assert(),在Release版本中会自动优化掉assert();
传值调用和传址调用
什么是传值调用?
传值调用就是直接将实参的值传递给形参。
传值调用:实参和形参的值相同,但是函数的实参和形参分别占有不同的内存块,二者均是独立的个体,只是二者的值相同;
实际上二者并没有建立联系;
我们来举一个例子:
下面是一个比较典型的传值调用:
int add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10;
int b = 20;
int c = add(a, b);
}
我们来写一个函数交换两个变量的值:
错误写法:
void swap(int x, int y)
{
int t = x;
x = y;
y = t;
}int main()
{
int a = 10;
int b = 20;
swap(a, b);
printf("a=%d\n", a);
printf("b=%d\n", b);
}
这样写我们发现:a和b的值并没有交换;
那是什么原因造成的?
我们来调试一下:
我们发现:
a和x的地址,b和y的地址不相同,函数里面x,y的交换,主函数里面a,b并不会改变;
那这个函数应该怎么写?
如果我们将实参和形参联系起来,是不是就可以了;
怎么把他们联系起来?-----------传址调用
什么是传址调用?
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
void swap(int *x, int *y)//int *pa=&a;
{
int t = *x;//a
*x = *y;//b
*y = t;
}
int main()
{
int a = 10;
int b = 20;
swap(&a, &b);
printf("a=%d\n", a);
printf("b=%d\n", b);
}
我们发现x和a,y和b的地址相同;
数组名的理解
我们知道,数组名大部分是数组首元素的地址;除了两个例外:
int arr[10]={0};
1、sizeof(arr) : 这里的arr为整个数组, sizeof(arr)代表的是整个数组的大小;
2、&arr :arr表示整个数组,&arr取出的是整个数组的地址;
除此之外,其余都是首元素的地址;
int main()
{
int arr[10] = { 0 };
printf("%d\n", sizeof(arr));
printf("%p\n", &arr[0]);//int *
printf("%p\n", arr);//int *
printf("%p\n", &arr);
}
那我们就要问了,既然&arr是整个数组的地址,那为什么打印&arr的结果和arr,&arr[0]相同?
根据下图,不论是取出的整个地址还是首地址,我们指针一开始指向的位置都是一样的 ;
一维数组传参本质
1、因为数组在内存中是连续存放的;
2、数组名就是首元素的地址(很方便找到起始位置);
我们可以使用指针访问数组;
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = &arr[0];
for (int i = 0; i < sz; i++)
{
/*scanf("%d", &arr[i]);*/
/*scanf("%d", p + i);*/
scanf("%d", arr+i);
}
for (int i = 0; i < sz; i++)
{
/*printf("%d ", *(p + i));*/
/*printf("%d ", *(arr + i));*/
printf("%d ", i[arr]);//-->*(i+arr)--->*(arr+i)--->arr[i]
//2+3=3+2
//arr[i]==*(arr+i);
// *(i+arr)==i[arr];
//p[i]==*(p+i);
}
}
我们知道:数组传参,传递的并非是数组,而是数组首元素的地址:
int main()
{
int arr[10] = { 0 };
test(arr);//传递是数组首元素的地址
}
我们就可以这样写:
void test(int arr[])//int *arr
{
int sz = sizeof(arr) / sizeof(arr[0]);
//sizeof(arr)//一个指针变量的大小
printf("%d\n", sz);
}
void test(int *arr)//int *arr
{
int sz = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", sz);
}
冒泡排序
什么是冒泡排序?
冒泡排序:相邻的两个进行交换,如果不满足就交换;
代码:
#include<stdio.h>
void bubblesort(int *arr,int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
//一趟冒泡排序的过程
for (int j = 0; j < sz - i-1; j++)
{
if (*(arr + j) > *(arr + j + 1))
{
int t = *(arr + j);
*(arr + j) = *(arr + j + 1);
*(arr + j + 1) = t;
}
}
}
}
void Print(int* arr,int sz)
{
for (int i = 0; i < sz; i++)
printf("%d ", *(arr + i));
}
int main()
{
int arr[10] = { 2,1,5,4,6,3,7,8,9,0 };
//排成升序
//冒泡排序:相邻的两个进行交换,如果不满足就交换
int sz = sizeof(arr) / sizeof(arr[0]);
bubblesort(arr,sz);
Print(arr,sz);
return 0;
}
以上就是指针(2)的全部内容,希望有所帮助!