一篇文章带你入门C语言:操作符

目录
  • 操作符
    • 分类
    • 算术操作符
    • 移位操作符
    • 整数存储规则
    • 左右移位规则
    • 赋值操作符
    • 单目操作符
    • 取地址操作符& 解引用操作符*
    • 类型长度操作符sizeof
    • 按位取反操作符~
    • ++ -- 操作符
    • 强制类型转换操作符(type)
    • 关系操作符=
    • 逻辑操作符
    • 短路运算
    • 条件操作符
    • 逗号表达式
    • 下标引用、函数调用和结构成员
    • 下标引用操作符[]
    • 函数调用操作符()
    • 结构成员操作符. ->
    • 结构体定义
    • 结构体使用
    • 结构体地址
    • 表达式求值
      • 隐式类型转换
      • 整型提升
    • 如何整型提升
    • 有符号数
    • 无符号数
    • 算术转换
    • 操作符的属性
  • 总结

操作符

分类

算术操作符

移位操作符

位操作符

赋值操作符

单目操作符

关系操作符

逻辑操作符

条件操作符

逗号表达式

下标引用、函数调用和结构成员

算术操作符

+ - * / %

//1.
int ret = 9 / 2;
printf("%d", ret);//4
//2.
double ret2 = 9 / 2;
printf("%lf", ret2);//4.000000
//3.
double ret3 = 9 / 2.0;
printf("%lf", ret3);//4.500000

从这两个对比可以看出,不是存储的问题,而是计算机里9/2就是等于4,怎么存都是4。

要想得到正确结果,则要改成9.0/2或者9/2.0。

/ 的两个操作数都为整数时,执行整数除法,只要有浮点数就执行浮点数除法。% 的两个操作数必须为整数,所得结果的范围在 [ 0 , 除 数 − 1 ] [0, 除数-1] [0,除数−1] 之间。

接下来的移位操作符和位操作符都是较为复杂的,涉及到二进制位。

移位操作符

<< //左移操作符
>> //右移操作符

整数存储规则

移位操作符移动的是二进制位,整数在内存中存储的是二进制补码,移位操作的也是内存中的补码。

整数在内存中的存储:

  • 正数: 原

    • 码反码补码相同
  • 负数:
    • 原码:二进制序列
    • 反码:原码符号位不变,其他位按位取反
    • 补码:反码 + 1

左右移位规则

知道二进制位如何转化后,我们再来看移位操作符的移动规则。

1.左移操作符

左边舍弃,右边补0

int a = 5;
int b = a << 1;

a<<1的意思就是a的补码向左移动一位,正数的原反补相同,所以得补码为00000000 00000000 00000000 00000101 ,向左移动一位得00000000 00000000 00000000 00001010,换算一下就可得到10。

此时a的值还是5,可以类比b=a+1,a并不会发生变化。

int c = -1;
int d = c << 1;

先写出 -1的原码,再取反加一得补码,补码向左移动一位,然后将得到的补码按相同规则换算成原码,就可以得到 -2了。

10000000 00000000 00000000 00000001 - -1的原码
11111111 11111111 11111111 11111110 - -1的反码
11111111 11111111 11111111 11111111 - -1的补码

11111111 11111111 11111111 11111110 - -1<<1的补码
11111111 11111111 11111111 11111101 - 反码
10000000 00000000 00000000 00000010 - 原码 = -2

2.右移操作符

右移规则分两种,一种是逻辑右移一种是算术右移。但绝大多数编译器都是采用算术右移。

算术右移:左边补原符号位,右边舍弃

逻辑右移:左边补0,右边舍弃

int a = -1;
printf("%d\n", a >> 1);
//10000000 00000000 00000000 00000001 - 原码
//11111111 11111111 11111111 11111110 - 反码
//11111111 11111111 11111111 11111111 - 补码
//11111111 11111111 11111111 11111111 - 补码

逻辑右移会把负数搞成整数,所以算术右移显得更正确一些。

值得一提的是,-1的补码右移一位后仍是-1。

补充:

不难发现左移使数据变大,右移使数据变小,左移就是数据 × 2 ×2 ×2,右移即数据 ÷ 2 ÷2 ÷2 。左移右移操作数必须为整数。移位操作符不可移动负数位,即1>>-1,标准未定义行为。

位操作符

& //按位与
| //按位或
^ //按位异或

同样位操作符也是按二进制位。

运算规则

按位与 &

全1则1,有0则0

按位或 |

有1则1,全0则0

按位异或 ^

相同为0,相异为1

通过运算规则可以看出,按位与和按位或和逻辑与、逻辑或还是有异曲同工之妙的。

int a = 3;
int b = -2;
int c = a & b;
//1.求a的补码
100000000 000000000 000000000 000000010 - -2的原码
111111111 111111111 111111111 111111101 - -2的反码
111111111 111111111 111111111 111111110 - -2的补码
//2.求b的补码
000000000 000000000 000000000 000000011 -  3的原反补相同!!
//3.求a & b
111111111 111111111 111111111 111111110 - -2的补码
000000000 000000000 000000000 000000011 -  3的补码
000000000 000000000 000000000 000000010 - 所得数的补码!! (全1为1,有0则0)
//4.转化为原码
000000000 000000000 000000000 000000010 - 正数的原反补相同

计算方法

  • 求两操作数的补码
  • 计算按位与、或、异或的结果
  • 将所得补码转换成原码

将a和b的补码求出来,然后再按位与、或,得到所得数的补码,再转换成原码。这几步很绕人,前往别被带沟里了。其他两个除了运算规则不一样外,其他都一样。

注意

1.整数的原反补相同,可别照负数的规范求。

2.按位与、按位或的结果同样是补码,最后还需转换成原码。

例题

不创建临时变量,实现两数交换。

int a = 10;
int b = 20;
printf("a=%d,b=%d\n", a, b);
//1.
a = a + b;
b = a - b;//(a+b)-b = a
a = a - b;//(a+b)-a = b
printf("a=%d,b=%d\n", a, b);
//溢出风险

//2.
a = a ^ b;
b = a ^ b;//(a ^ b) ^ b = a
a = a ^ b;//(a ^ b) ^ a = b
//可读性差,只支持正数

a^b的值再和a异或,则得到b;a^b的值再和b异或,则得到a。a ^ a = 0 a ^ 0 = a(a ^ a) ^ b = b (a ^ b) ^ a = b ,由此也可以说异或支持交换律

用处

给出一个正整数,想知道其(如果是负数的话,就是补码)二进制位最低位是0是1,怎么办?

将这个正整数按位与1,如果所得结果为1则最低位为1,反之则为0。如:

int a = 15;
int b = a & 1;
00000000 00000000 00000000 00001111 - 15原反补相同
00000000 00000000 00000000 00000001 - 1
00000000 00000000 00000000 00000001 - b=1原反补相同

从这个例子可以看出某个正数&1,所得结果为1则最低位为1,反之则为0。如果搭配上>>右移操作符,可以得到每一位的数字。 如:

int num = 15;
int count = 0;
for (int i = 0; i < 32; i++)
{
    if (((num >> i) & 1) == 1){
        count++;
    }
}
printf("%d\n", count);

赋值操作符

=
//复合赋值符
+= -= *= /= %= >>= <<=

赋值操作符没什么讲头,我们来看看一些奇葩的东西。

int a = 10;
int x = 0;
int y = 20;
a = x = y+1;//连续赋值

如何理解这个连续赋值呢?

先是把y+1赋值给了x,再把表达式x=y+1的值赋值给了a 。

单目操作符

! //逻辑反操作
- //取负
+ //取正
& //取地址
sizeof //操作数的类型长度
~ //按位取反
-- //前后置——
++ //前后置++
* //解引用操作符
(type) //强制类型转换

逻辑反操作!

非零即为真,零为假,默认规定 !0=1

取地址操作符& 解引用操作符*

int a = 10;
int* p = &a;//* - 说明p为指针变量 ,& - 说明p中存储的是a的地址
*p = 20;//解引用访问其存储的地址中的内容
printf("%d\n", *p);

数组名作首元素地址问题

int arr[10] = { 0 };
//1.
printf("%p\n", arr + 1);
//2.
printf("%p\n", &arr[0] + 1);
//3.
printf("%p\n", &arr + 1);

arr和arr[0]都是首元素的地址,&arr是整个数组的地址,打印出来都是一样的。但是当他们都+1区别就出现了,前两个加1都是第二个元素的地址,而&arr加1就跳过了整个数组的地址。

拓宽一点,*p放在=左边就是一块空间,而放在=右边就是一个值。

//1.
int b = *p;//这里*p代表值
//2.
*p = b;//这里*p就代表一块空间用以存放值

任何一个变量都可以这样理解,放在=的左边代表一块空间a = 10;,就是左值。放在=右边就是代表值p = a;,即右值。

类型长度操作符sizeof

sizeof计算变量或类型所占内存空间的大小,与其内存中存放的数据是什么无关。

//1.
printf("%d\n", sizeof arr);
//2.
printf("%d\n", strlen(arr));

sizeof strlen() 二者的区别

sizeof 是计算所占空间的操作符,不关心存放的数据strlen() 是计算字符串长度的函数,关注存放的数据中的\0 前的字符个数

sizeof 后面的()是表达式的括号,而不是函数调用操作符,正因sizeof 是操作符,所以可以省略。

例题:

int a = 5;
short s = 10;
printf("%d\n", sizeof(s = a + 2));//?
printf("%d\n", s);//?

把int型数据a+2赋值给short型数据s,会发生整型截断,还是short 型的数据。

sizeof 内部的表达式是不参与运算的,所以s原来是多少现在还是多少。原因:sizeof内部的运算时再预编译时期处理的,在程序执行期间早已将内部的表达式替换成了数字。

按位取反操作符~

将其二进制位所有位统统取反。

例题

如何将二进制位指定一位1修改为0,0修改为1?

int a = 13;
//00000000 00000000 00000000 00001101 - 13
//00000000 00000000 00000000 00000010 - 1<<1
//00000000 00000000 00000000 00001111 - 15
int b = a | (1<<1);
printf("%d\n", b);
//00000000 00000000 00000000 00001111 - 15
//11111111 11111111 11111111 11111101 - ~(1<<1)
//00000000 00000000 00000000 00001101 - 13
int c = b & (~(1 << 1));
printf("%d\n", c);

该二进制位为0想改为1,则按位或上这么一个数字..00100..。该二进制位为1想改为0,则按位与上这么一个数字..11011..

++ -- 操作符

前置++ --是先使用在修改,后置++ --先修改再使用。

int a = 0;
printf("%d\n", a);
int b = a++;
printf("%d\n", b);
int c = --a;
printf("%d\n", c);

++ --这样使用就可以了,不要去追求一些没用的复杂使用,没人会去那么用的,写代码的目的并不是不让人看懂。如:

int a = 0;
int b=(++a)+(a++)+(a++);

这样的代码再不同的编译器上会跑出不同的结果,没必要在这个上浪费时间。

强制类型转换操作符(type)

int a = (int)3.14;

例题

void test1(int arr[]){
	printf("%d\n", sizeof(arr));//(2)
}
void test2(char ch[]){
	printf("%d\n", sizeof(ch));//(4)
}
int main(){
	int arr[10] = { 0 };
	char ch[10] = { 0 };
	printf("%d\n", sizeof(arr));//(1)
	printf("%d\n", sizeof(ch));//(3)
	test1(arr);
	test2(ch);
	return 0;
}

(1) 和 (3) 没问题,数组名单独放在sizeof内,计算的是整个数组的大小,分别是40和10。(2) 和 (4) 是数组名作函数参数。别看表面上是用数组接收,其实是用指针接收的,计算的都是指针的大小。数组名作函数参数,没有可能将数组整个传参过去,编译器自动将其降级优化为指向元素首地址的指针。

关系操作符=

> >= < <= != ==

==和=不一样,如果写错就成赋值了。

逻辑操作符

&& //逻辑与
|| //逻辑或

逻辑操作符只关注真假,逻辑与 && 就是并且,逻辑或 || 就是或者。

逻辑与 && 两边操作数都为真,整个条件才为真,逻辑或 ||两边操作数有一个是真,则整个条件就为真。

例题

int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++ && ++b && d++;
i = a++||++b||d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}

短路运算

1.逻辑与 &&,当左边的表达式为假时,整个条件为假,不再进行运算。

2.逻辑或 +,当左边的表达式为真时,整个条件为真,不再进行运算。

i = a++ && ++b && d++,第一步a++=0为假,则整个表达式为假,i=0;i = a++||++b||d++,第二步a++为真,整个表达式为真,后面的表达式也不进行运算了。

条件操作符

exp1 ? exp2 : exp3

表达式exp1的结果为真,执行exp2并将exp2的结果作为整个表达式的结果,反之,则执行exp3并将其赋值给整个表达式。

逗号表达式

exp1, exp2, exp3,...,expN

从左向右依次计算,整个表达式的结果为最后一个表达式的结果。

那既然这样,为什么我们还要计算前面的表达式呢,直接算最后一个不就好了吗?

前面的表达式可能会影响到最后一个表达式的值。如:

int a = 1,b = 2;
int c = (a>b, a=b+10, a, b=a+1);

下标引用、函数调用和结构成员

   []   ()   .   ->

下标引用操作符[]

arr+i即为数组中下标为i的元素的地址。

[]是一个操作符,它的两个操作数分别为数组名和下标,缺一不可。对于arr[i]可理解为*(arr+i),既然如此我们就可写出:

arr[i] <=> *(arr+i) <=> *(i+arr) <=> i[arr]
int arr[10] = { 0 };
for (int i = 0; i < 10; i++){
    printf("%p --- %p\n", &i[arr], i+arr);
}

这就体现出了[]是个操作符,这样的写法语法是支持的。

函数调用操作符()

printf("%u\n", strlen("abc"));

这里printf和strlen函数都必须带上(),不传参也要带上,不然就错。

对于函数调用操作符(),可以有一个或者两个操作数都可以。

结构成员操作符. ->

. 结构体.成员名

-> 结构体指针 -> 成员名

结构体用于描述一个复杂的对象。

结构体定义

struct Book{
	char name[50];
	char id[15];
	float price;
};

结构体使用

Print(struct Book b1){
	printf("书名为:%s\n", b1.name);
	printf("价格为:%f\n", b1.price);
	printf("书号为:%s\n", b1.id);
}
int main(){
	struct Book b1 = { "谭浩强C语言程序设计",55.5f,"2020322222" };
	Print(b1);
	return 0;
}

使用结构体类型struct Book创建了一个结构体类型的变量b,b中成员有三个name、id和price。

我们还可以后续去修改价格,如:

b1.price = 100.0f;

那我们能不能把书名或者书号都给改了呢?

b1.name = "数据结构";

当然是不行的,我们可以看得出,书名name和书号id都是通过数组创建的。对于他们来说b1.name是数组的首地址。怎么能对地址赋值呢。

那既然是地址的话,我们对地址进行解引用,不就可以访问数组元素了嘛~,我们再试一下。

*(b1.name) = "数据结构";

当然,仍然是不对的,会显示乱码。

那如何结构体变量的数组成员呢,答案是使用库函数strcpy对字符串赋值

strcpy(b1.name, "数据结构");

结构体地址

将变量地址传过去,如何使用呢?

1.(*结构体指针).成员名

Print2(struct Book* pb){
	printf("书名为:%s\n", (*pb).name);
	printf("价格为:%f\n", (*pb).price);
	printf("书号为:%s\n", (*pb).id);
}

2.结构体指针->成员名

Print3(struct Book* pb){
	printf("书名为:%s\n", pb->name);
	printf("价格为:%f\n", pb->price);
	printf("书号为:%s\n", pb->id);
}

表达式求值

一个表达式在求值时,一部分取决于它的操作符的优先级和结合性,一部分取决于编译器自己的规则。我们写出的表达式一定要让编译器的逻辑与自己的代码逻辑相一致,否则就是没用的代码。与此同时,有一些表达式中的操作数可能需要类型提升。

隐式类型转换

在运算的过程中,一些小字节的类型会向大字节的类型转换后再加以运算,整个过程是编译器自动一次完成的。

整型提升

如,short和char会转化为int,再进行运算。不是说只有不同类型数据运算时才会发生类型转换,而是为适应CPU4个字节的运算器,都会转化为普通整型,这个过程被称为整型提升。只要有运算就会有整型提升。如:

char a=1,b=2,c=3;
...
char d=a+b+c;

如这样的一个例子,先将字符型的a,b,c整型提升为普通整型,然后进行运算,再放到d中,最后再发生截断,只取最后一个字节,转化回为字符型。

如何整型提升

按类型的符号位进行整型提升。如:

char c = -1;
//11111111 11111111 11111111 11111111
//11111111
printf("%d\n",c);
//11111111 11111111 11111111 11111111

有符号数

写出变量的二进制补码按最高位符号位进行填充得到的补码再转换成原码

无符号数

最高位填充0

如何得到c的补码?(1)先把c当成int类型然后,写出32位补码,(2)然后进行截断,只得最后8位。(3)最后再按此时的最高位填充,是0就填充0,反之则1。

例题

Example 1

char a = 3;
//00000000 00000000 00000000 00000011 - int a
//00000011 - char a
char b = 127;
//00000000 00000000 00000000 01111111 - int b
//01111111 - char b
char c = a + b;
//00000000 00000000 00000000 00000011 - int a 发生整型提升
//00000000 00000000 00000000 01111111 - int b
//00000000 00000000 00000000 10000010 - int c
//10000010 - char c 发生截断
printf("%d\n", c);
//11111111 11111111 11111111 10000010 - int c - 补码 发生整型提升
//10000000 00000000 00000000 01111110 - int c - 原码

写出a 和b的32位补码进行截断,存入内存整型提升,按最高位进行填充进行运算进行截断,再整型提升将所得补码转换回原码

如:

我们在得到两个变量的二进制码后,对其进行整型提升,再对所得结果进行截断,因为要存入字符型变量c中。又因为要以%d的形式打印变量c,再次对已经截断过的补码(存入内存中的都是补码),进行整型提升,转换成原码。

Example 2

char a = 0xb6;
//10110110
short b = 0xb600;
//10110110 00000000
int c = 0xb6000000;
//10110110 00000000 00000000 00000000
if (a == 0xb6)
	//11111111 11111111 11111111 10110110
	//10000000 00000000 00000000 01001001
	//10000000 00000000 00000000 01001010 - int a
	//00000000 00000000 00000000 10110110 - 0xb6
	printf("a");
if (b == 0xb600)
	//11111111 11111111 10110110 00000000
	//10000000 00000000 01001001 11111111
	//10000000 00000000 01001010 00000000 - int b
	//00000000 00000000 10110110 00000000 - 0xb600
	printf("b");
if (c == 0xb60000)
	//10110110 00000000 00000000 00000000 - int c
	//10110110 00000000 00000000 00000000 - 0xb6000000
	printf("c");

首先我们写出a,b,c 的二进制补码(都是正数)。然后发现有运算(==也是运算),只要有运算就要整型提升,整型提升后好巧不巧最高位都是1,默认为负数了。这样经过原反补转化后无论怎样都是负数,不会和0xb6和0xb600相等的。只有c本身就是默认整型,不用提升。

Example 3

char c = 1;
printf("%u\n", sizeof(c));//1
printf("%u\n", sizeof(+c));//4
printf("%u\n", sizeof(-c));//4

计算sizeof(c)时,没有运算所以没有发生整型提升。取正取负也是运算符,sizeof(±c)时(+c)和(-c)两个表达式发生了整型提升,故变成了四个字节。

算术转换

对于short和char需要整型提升为int,那浮点型,长整型呢?对于这些类型,就不叫整型提升了,叫算术转换。

顺序由高到低,当精度低的类型与精度高的类型相运算时,会将低精度转换为高精度,然后在和高精度数据进行运算。例:

int a = 4;
float f = 4.5f;
f = a + f;
printf("%f\n", f);//8.500000

计算f时需要先把a转化为单精度浮点型。

操作符的属性

表达式的求值有三个影响因素:

  • 操作符的优先级
  • 操作符的结合性
  • 是否控制求值顺序

两个相邻的操作符先执行那个?

先看优先级,优先级相同看结合性。

//表达式1.
a*b+c*d+e*f;
//表达式2
c + --c;
//表达式3
int a = 1;
a=(++i)+(++i)+(++i);

这样的表达式在不同的编译器下,会跑出不同的结果,因为各个编译器的标准不一样。

对于这样的表达式,我们知道操作符的优先级和结合性,但我们依然无法确定表达式计算的唯一路径,所以这样的代码是不好的,宁愿多写几步,规范确定出表达式的唯一执行路径,也不要追求过分的简洁,这不是代码的目的。

总结

我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。

本篇文章就到这里了,希望能给你带来帮助,也希望能够您能够多多关注我们的更多内容!

(0)

相关推荐

  • C语言中各种操作符的详细介绍(纯干货!)

    目录 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 (类型)   强制类型转换 条件操作符 总结 算术操作符 主要是 ( +   -   *   /    %) 五种算数操作符. 1.除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数. 2. 对于 / 操作符如果两个操作数都为整数,执行整数除法.而只要有浮点数执行的就是浮点数除 法. 3..% 操作符的两个操作数必须为整数.返回的是整除之后的余数. 当除数为小数时,int类型只会截取整数部分. 移位操作符 << 左移操作

  • C语言安全编码之数值中的sizeof操作符

    通常来说获取数组的长度时不要对指针应用sizeof操作符. 现来看看下面这段代码: void clear(int array[]) { for(size_t i = 0; i < sizeof(array) / sizeof(array[0]); i++) { array[i] = 0; } } void dowork(void) { int dis[12]; clear(dis); /*...*/ } clear()使用sizeof(array) / sizeof(array[0])这种用法确

  • 关于C语言操作符的那些事(超级全)

    目录 前言 操作符的分类 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用符 函数调用符 结构体调用操作符 总结 前言 C语言中操作符不多,但是有些相同的操作符都是在不同的表达式中,有不同的解释意思,比如 * 号,在表达式中5*5表示乘号,在int *p表示指针,在 *p = 10中,又表示解引用,所以今天就来详细的整理一下C语言中的操作符,做到心中有数,可以一眼识破,用途有哪些.重点不是记忆:是理解,兄弟们,要动本质. 操作符的分类 注意:

  • C语言中的sizeof操作符用法及和strlen的区别

    一. 定义: sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数.其返回值类型为size_t,在头文件stddef.h中定义.在32位系统中: char的sizeof值为1,char是我们编程能用的最小数据类型. short的sizeof值为2: int.float.long为4: double为8: 所有的指针的sizeof值都为4. 二.语法: sizeof有三种语法形式,如下: 1) sizeof( object ); //

  • C语言中的操作符优先级的详细介绍

    C语言中的操作符优先级的详细介绍 C语言中操作符的优先级大全, 当然c++, Objective-C,大部分语言都试用. 下面是来自The C Programming Language 2th的总结. OperatorsAssociativity(结合性) 1. () [] -> . 左->右 2. ! ~ ++ -- + - *(type)sizeof 右->左 3. * / % 左->右 4. + - 左->右 5. << >> 左->右 6

  • 一篇文章带你入门C语言:操作符

    目录 操作符 分类 算术操作符 移位操作符 整数存储规则 左右移位规则 赋值操作符 单目操作符 取地址操作符& 解引用操作符* 类型长度操作符sizeof 按位取反操作符~ ++ -- 操作符 强制类型转换操作符(type) 关系操作符= 逻辑操作符 短路运算 条件操作符 逗号表达式 下标引用.函数调用和结构成员 下标引用操作符[] 函数调用操作符() 结构成员操作符. -> 结构体定义 结构体使用 结构体地址 表达式求值 隐式类型转换 整型提升 如何整型提升 有符号数 无符号数 算术转换

  • 一篇文章带你了解C语言操作符

    目录 一.操作符分类 二.算术操作符 三.移位操作符 1.左移操作符 2.右移操作符 2.1算术移位 2.2逻辑移位 四.位操作符 1.按位与 2.按位或 3.按位异或 4.一道练习题 五.赋值操作符 1.赋值操作符(=)是一个很棒的操作符,他可以让你得到一个你之前不满意的值.也就是你可以对其重新赋值. 2.赋值操作符可以连续使用 3.复合赋值符 六.单目操作符 1.逻辑反操作 2.取地址 3.sizeof 4.++和--运算符 4.1前置++和-- 4.2后置++和-- 七.关系操作符 八.逻

  • 一篇文章带你入门C语言:函数

    目录 函数 定义 库函数 定义 介绍 Example 1 strcpy Example 2 memset 自定义函数 Example 1 Example 2 两数交换 链式访问 Example 1 函数声明 函数递归 Example 1 Example 2 函数迭代 Example 3 Example 4 总结 函数 定义 程序里的函数又被叫做子程序,他作为一个大型程序的部分代码,有一或多个语句项组成.函数负责完成某项特定任务,提供了对过程的封装和对细节的隐藏,这样的代码通常会被集成为软件库.

  • 一篇文章带你入门C语言:数组

    目录 数组 一维数组 初始化 使用 总结: 内存存储 二维数组 创建 初始化 数组越界问题 数组作函数参数 应用实例 总结 数组 一维数组 创建 定义 数组是一组相同类型的元素的集合.那数组的语法形式: type_t arr_name [const_n] //如: int arr[10]; type_t 指的是数组元素的类型. const_n 指的是一个常量表达式,用来指定数组的大小. 此时运行程序的话,系统会报一个警告:未初始化变量.打开调试就会发现系统默认填入一些无意义的数据. 当然全局数组

  • 一篇文章带你入门C语言数据结构:绪论

    目录 绪论 什么是数据结构? Example 1 讨论 Example 2 Example 3 Example 4 总结 绪论 什么是数据结构? 不同于计算机操作培训,注意与程序设计的区别. Example 1 求n个数的最大值.次最大值. //1.遍历 - 最朴素的方法 int main() { int arr[10] = { 22,334,552,1,4,6,78,23,55,98 }; int i = 0; int temp = 0; int max1 = arr[0]; int max2

  • 一篇文章带你入门Springboot沙箱环境支付宝支付(附源码)

    目录 0.前言 1.效果展示 2.技术栈介绍 3.前期准备 第一步:申请一个沙箱测试账号 第二步:电脑下载一个支付宝提供的客户端用于生成RSA2 第三步:手机下载 [沙箱版支付宝] 4.后端搭建 项目目录结构 pom.xml application.yml application-alipay.proerties Order订单实体类 Service层 Controller层 配置类 跨域拦截器配置以及注册 启动spirngboot项目 支付操作的页面: 支付完成后支付宝回调的页面: 启动前端项

  • 一篇文章带你了解C语言:入门基础(2)

    目录 操作符 算术操作符 移位操作符 位操作符 单目操作符 逻辑反操作! 操作符++,-- 逻辑操作符 条件操作符 逗号表达式 常见关键字 typedef extern static 修饰局部变量 修饰全局变量和函数 其它 #define定义常量和宏 定义常量 定义宏 指针 内存单元 指针变量 &取地址操作符,*解引用操作符 类型所占空间 结构体 定义结构体 使用结构体变量 总结 本节将结束对初识C语言的概述,只追求大概,不求精细. 本节包括的内容有操作符,常见关键字,#define定义常量和宏

  • 一篇文章带你了解C语言:入门基础

    目录 C语言本身特点 数据类型 常量变量 变量分类 使用小建议 生命周期作用域 常量分类及其特点 字符串+转义字符+注释 字符串 转义字符 两种注释 选择循环语句 函数 数组 总结 闲话少说,先上思维导图. 如图所示,现在还是初识C语言的第一部分,本次只介绍了C语言本身特点,数据类型,常量变量,字符串转义字符注释,选择循环语句,函数,数组. 接下来请和我一起粗略地探讨其中内涵所在. C语言本身特点 这是C语言的定义: C语言是一门通用计算机编程语言,广泛应用于底层开发.C语言的设计目标是提供一种

  • 一篇文章带你入门Springboot整合微信登录与微信支付(附源码)

    0. 前期准备 在使用微信支付前,默认小伙伴已经具备以下技能: 熟练使用springboot(SSM) + Mybatis(plus)/JPA + HttpClient + mysql5.x 了解JWT 权限校验 阅读过微信开放平台微信支付与微信登录相关文档,可以简单看懂时序图 有微信开放平台开发者资质认证账户,具备开通微信支付(如果不具备的小伙伴可以找身边有的人借一下) 1. 微信扫码登录 1.1 微信授权一键登录功能介绍 简介:登录方式优缺点和微信授权一键登录功能介绍 # 1.手机号或者邮箱

  • 一篇文章带你入门Java修饰符

    目录 定义 分类 访问控制修饰符 非访问控制修饰符 修饰符的使用说明 修饰类 修饰方法 访问控制修饰符 非访问控制修饰符 修饰变量 总结 定义 Java修饰符:修饰符用来定义类.方法或者变量,通常放在语句的最前端. 分类 主要分为2类: 访问控制修饰符 非访问控制修饰符 访问控制修饰符 可以使用访问控制符来保护对类.变量.方法和构造方法的访问.分为以下4中权限:private,default,protected,public. 权限说明: 修饰符 当前类 同包 子类(不同包) 不同包(其他类)

随机推荐