文章目录
一、地址
(重点)可以发现,对应字节的地址,他是连续起来的;所以可以之后得到了,变量的起始地址,也可以获得后面字节的地址;
代码理解:
#include<stdio.h>
int main() {
int a = 1;
//%p是地址的格式占位符
//&a就是对变量a进行取地址
//取的地址也是对应字节的起始地址
printf("&a = %p\n", &a);
return 0;
}
执行结果:
这里的结果一般来说是不一样的,但是只要是0x开头的16进制就说明没有问题
16进制
在程序中十六进制的表示,以及使用:
#include <stdio.h>
#include <limits.h>
int main() {
//如果要用十六进制对变量赋值
//需要在赋值前加上0x
int a = 0x6f;
//打印a变量对应10进制的值
printf("a(10) = %d\n", a);
//打印a变量对应16进制的值
//%x是十六进制对应的格式占位符
printf("a(16) = %x\n", a);
//打印a变量对应16进制的值
//%X是十六进制对应的格式占位符
//但是对应小写和大写的作用是
//打印时十六进制不是会有字母吗
//然后这里的大小写对应就是把那些字母规定打印时是小写还是大写
printf("a(16) = %X\n", a);
//用16进制表示整形最大值和最小值
printf("MAX_INT = %d\n", INT_MAX);
printf("MIN_INT = %d\n", INT_MIN);
int max_int = 0x7fffffff;
int min_int = 0x80000000;
printf("max_int = %d\n", max_int);
printf("min_int = %d\n", min_int);
return 0;
}
执行结果:
对应的最大值2进制转换的十六进制0x7fffffff如何来的:
通过这张图,也可以推出0x80000000如何来的
地址是一个几位二进制数据
先看一段程序:
#include<stdio.h>
int main() {
int a;
double b;
char c;
//获取每个类型的地址长度
//sizeof获取参数的对应字节长度
printf("sizeof(int &) = %lu\n", sizeof(&a));
printf("sizeof(double &) = %lu\n", sizeof(&b));
printf("sizeof(char &) = %lu\n", sizeof(&c));
return 0;
}
执行结果:
可以发现每个类型对应的地址都是8位,那么一定就是每个类型对应的地址都是8位吗?
来看32位操作系统和64位操作系统
通过对32位和64系统的理解后,可以发现地址不应的是8位的,要看操作系统是多少位有关系的。
二、数组
定义和使用
程序中如何使用数组,以及概念对应的代码:
#include<stdio.h>
//数组定义和使用
void test1() {
int a[5] = {
0};
for (int i = 0; i < 5; i++) {
//a[i] 就可以访问数组对应下标为i的位置
//也可以进行赋值
a[i] = 2 * i;
}
for (int i = 0; i < 5; i++) {
printf("a[%d] = %d\n", i, a[i]);
}
return ;
}
//动态数组的定义和使用
void test2() {
//通过执行程序时来定义数组想要的大小
int n;
scanf("%d", &n);
//动态数组是无法初始化的
int a[2 * n];
for (int i = 0; i < 2 * n; i++) {
a[i] = i * i;
}
for (int i = 0; i < 2 * n; i++) {
printf("a[%d] = %d\n", i, a[i]) ;
}
return ;
}
//初始化进行对数组赋值
void test3() {
// int a[5] = {0}; 这种初始化是将每个位置初始化为0
int a[5] = {
1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {
printf("a[%d] = %d\n", i, a[i]);
}
return ;
}
//数组定义时不在[]中输入大小
void test4() {
int a[] = {
1, 2, 3, 4, 5, 6, 7};
//sizeof(a)获取数组字节大小
//sizeof(int)获取int类型字节大小
//相除就可以得到数组元素的个数
int len = sizeof(a) / sizeof(int);
printf("sizeof(a) / sizeof(int) = %d\n", len);
for (int i = 0; i < len; i++) {
printf("a[%d] = %d\n", i, a[i]);
}
return ;
}
//数组的地址理解
void test5() {
int a[5] = {
1, 2, 3, 4, 5};
printf("a = %p\n", a);
for (int i = 0; i < 5; i++) {
printf("&a[%d] = %p\n", i, &a[i]);
}
return ;
}
int main() {
printf("test1()\n");
test1();
printf("test2()\n");
test2();
printf("test3()\n");
test3();
printf("test4()\n");
test4();
printf("test5()\n");
test5();
return 0;
}
执行结果:
通过test5()发现数组的地址也不是连续的啊,但是对于数组a的类型是整形,整形对应的字节是4字节,对于变量的地址就是他的起始地址,所以相差为4刚好满足连续条件,所以数组的元素是连续的。
素数筛
代码实现:
#include<stdio.h>
int prime[100] = {
0};
void init_prime(int n) {
//初始化0和1不是素数
prime[0] = prime[1] = 1;
for (int i = 2; i <= n; i++) {
if (prime[i]) continue;//如果被标记了,说明不是素数,就不用再去标记
for (int j = 2 * i; j <= n; j += i) {
prime[j] = 1;//标记当前数为合数
}