那就让我们快速复习、记录一下吧。
后面接着转战C++
C 环境设置
#include
#include
int main() {
printf("hello world! \n");
system("pause");
return 0;
}
运行输出:
PS D:\jave\Work Files\C\Studies\1 hello world> gcc .\hello_world.c -o out
PS D:\jave\Work Files\C\Studies\1 hello world> .\out.exe
hello world!
#include
#include
#include
int main() {
int size = 5555;
unsigned int usize = ((unsigned int)-1) - UINT_MAX;
float fsize = 555.123456;
long double ldsize = 555.123456;
char c = 'm';
char str[20] = "this is your name";
int* p = &size;
int negNum = -1;
printf("d : %d \n", size); // d : 5555
printf("000d : %000d \n", size); // 000d : 5555
printf("###d : %###d \n", size); // ###d : 5555
printf("--d : %--d \n", size); // --d : 5555
printf("++d : %++d \n", size); // ++d : +5555
printf(" d : % d \n", size); // d : 5555
printf("3d : %3d \n", size); // 3d : 5555
printf("6d : %6d \n", size); // 6d : 5555
printf("06d : %06d \n", size); // 06d : 005555
printf("ld : %ld \n", size); // ld : 5555
printf("o : %o \n", size); // o : 12663
printf("x : %x \n", size); // x : 15b3
printf("X : %X \n", size); // X : 15B3
printf("0X : %0X \n", size); // 0X : 15B3
printf("u : %u \n", usize); // u : 0
printf("#X : %#X \n", size); // #X : 0X15B3
printf("#x : %#x \n", size); // #x : 0x15b3
printf("f : %f \n", fsize); // f : 555.123474
printf("e : %e \n", fsize); // e : 5.551235e+002
printf("E : %E \n", fsize); // E : 5.551235E+002
printf("g : %g \n", fsize); // g : 555.123
printf("G : %G \n", fsize); // G : 555.123
printf(".2f : %.2f \n", fsize); // .2f : 555.12
printf(".3e : %.3e \n", fsize); // .3e : 5.551e+002
printf(".4E : %.4E \n", fsize); // .4E : 5.5512E+002
printf(".5g : %.5g \n", fsize); // .5g : 555.12
printf(".6G : %.6G \n", fsize); // .6G : 555.123
printf(".*f : %.*f \n", fsize); // .*f : 0.000000
printf(".*e : %.*e \n", fsize); // .*e : 5.346871e-315
printf(".*E : %.*E \n", fsize); // .*E : 5.346871E-315
printf(".*g : %.*g \n", fsize); // .*g : 5.34687e-315
printf(".*G : %.*G \n", fsize); // .*G : 5.34687E-315
printf("p : %p \n", p); // p : 0061FEFC
printf("d : %d \n", *p); // d : 5555
printf("c : %c \n", c); // c : m
printf("s : %s \n", str); // s : this is your name
printf("u : %u \n", negNum); // u : 4294967295
printf("lu : %lu \n", negNum); // lu : 4294967295
printf("llu : %llu \n", negNum); // llu : 4648094134073032703
system("pause");
return 0;
}
PS D:\jave\Work Files\C\Studies\2 printf_format> gcc .\printf_format.c -o out PS D:\jave\Work Files\C\Studies\2 printf_format> .\out.exe d : 5555
000d : 5555
###d : 5555
--d : 5555
++d : +5555
d : 5555
3d : 5555
6d : 5555
06d : 005555
ld : 5555
o : 12663
x : 15b3
X : 15B3
0X : 15B3
u : 0
#X : 0X15B3
#x : 0x15b3
f : 555.123474
e : 5.551235e+002
E : 5.551235E+002
g : 555.123
G : 555.123
.2f : 555.12
.3e : 5.551e+002
.4E : 5.5512E+002
.5g : 555.12
.6G : 555.123
.*f : 0.000000
.*e : 5.346871e-315
.*E : 5.346871E-315
.*g : 5.34687e-315
.*G : 5.34687E-315
p : 0061FEFC
d : 5555
c : m
s : this is your name
u : 4294967295
lu : 4294967295
llu : 4648094134073032703
#include
#include
int main() {
float f_var = 210.0f;
double ff_var = 2.123456789E+10;
printf("f_var=%.2f\n", f_var);
printf("ff_var=%.2e\n", ff_var);
system("pause");
return 0;
}
a.c
#include
extern int a;
extern int b;
int c;
extern int d;
int sum() {
return a+b+c+d;
}
int main() {
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);
printf("a+b=%d\n",a+b);
printf("c+a=%d\n",c+a);
printf("c+d=%d\n",c+d);
printf("sum()=%d\n",sum());
return 0;
}
b.c
int a = 1;
int b = 2;
extern int c;
int d = 3;
PS D:\jave\Work Files\C\Studies\extern var> gcc .\a.c .\b.c -o out
PS D:\jave\Work Files\C\Studies\extern var> .\out.exe
a=1,b=2,c=0,d=3
a+b=3
c+a=1
c+d=3
sum()=6
#include
#include
#define TIME 1000000000
int m, n = TIME; /* 全局变量 */
int main(void)
{
time_t start, stop;
register int a, b = TIME; /* 寄存器变量 */
int x, y = TIME; /* 一般变量 */
time(&start);
for (a = 0; a < b; a++);
time(&stop);
printf("register var use time: %ld s\n", stop - start);
time(&start);
for (x = 0; x < y; x++);
time(&stop);
printf("auto var use time: %ld s\n", stop - start);
time(&start);
for (m = 0; m < n; m++);
time(&stop);
printf("global var use time: %ld s\n", stop - start);
return 0;
}
PS D:\jave\Work Files\C\Studies\5 test time> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\5 test time> .\out.exe
register var use time: 0 s
auto var use time: 2 s
global var use time: 2 s
/*common.h*/
#ifndef __COMMON_H__
#define __COMMON_H__
#include
#include
#define SPLIT_LINE(title)\
printf("============ " #title " ==========\n");
#define LINE printf("\n");
#define LINE_F(format,args...) printf(#format "\n", args);
#define STR(msg) printf(#msg "\n");
#endif
#include
#include "common.h"
typedef struct tm TM;
int main() {
SPLIT_LINE(asctime test start)
TM tm;
tm.tm_year = 2020;
tm.tm_mon = 4;
tm.tm_mday = 21;
tm.tm_hour = 16;
tm.tm_min = 28;
tm.tm_sec = 18;
LINE_F(asctime(%p):%s, &tm, asctime(&tm));
SPLIT_LINE(asctime test end)
LINE
return 0;
}
============ asctime test start ==========
asctime(0061FEFC):Sun May 21 16:28:18 3920
============ asctime test end ==========
#include
#include "common.h"
int main() {
SPLIT_LINE(CLOCKS_PER_SEC test start)
LINE_F("CLOCKS_PER_SEC:%d", CLOCKS_PER_SEC);
SPLIT_LINE(CLOCKS_PER_SEC test end)
LINE
/*
============ CLOCKS_PER_SEC test start ==========
"CLOCKS_PER_SEC:1000"
============ CLOCKS_PER_SEC test end ==========
*/
return 0;
}
/*clock.c*/
#include
#include
#include "common.h"
int main() {
SPLIT_LINE(clock test start)
clock_t start, end;
double elapsed;
// 耗时:秒
#define ET_S (double)(end - start) / CLOCKS_PER_SEC
// 耗时:毫秒
#define ET_MS (end - start)
STR( --- 10000000 loop test --- )
start = clock();
for (size_t i = 0; i < 10000000; i++) {
// noops
}
end = clock();
LINE_F("elapsed time : %lfs", ET_S);
STR( --- Sleep(1000) test ---)
start = clock();
Sleep(1000);
end = clock();
printf("elapsed time : %lfs, start : %ld, end : %ld\n", ET_S, start, end);
SPLIT_LINE(clock test end)
LINE
return 0;
}
============ clock test start ==========
--- 10000000 loop test ---
"elapsed time : 0.014000s"
--- Sleep(1000) test ---
elapsed time : 1.002000s, start : 14, end : 1016
============ clock test end ==========
#include
#include "common.h"
// char *ctime(const time_t *timer)
int main() {
time_t curtime;
time(&curtime);
LINE_F(current time : %s, ctime(&curtime))
return 0;
}
// current time : Tue Apr 21 17:47:17 2020
#include
#include
#include "common.h"
// double difftime(time_t time1, time_t time2)
int main() {
time_t start;
time_t end;
time(&start); // all elapsed seconds from 1980'
LINE_F(start time : %ld, start)
STR(sleep time : 2 second)
Sleep(2000); // ms
time(&end);
LINE_F(end time : %ld. end - start time : %ld, end, end - start)
return 0;
/*
start time : 1587463061
sleep time : 2 second
end time : 1587463063. end - start time : 2
*/
}
#include
#include "common.h"
// 时差
#define BST_DIFF_HOURS (1)
#define CCT_DIFF_HOURS (8)
int main() {
time_t curtime;
struct tm *curtm;
time(&curtime);
// 使用 time_t 来填充 tm
curtm = gmtime(&curtime);
STR(current world time : )
LINE_F(West time : %2d:%02d, (curtm->tm_hour + BST_DIFF_HOURS) % 24, curtm->tm_min)
LINE_F(East time : %2d:%02d, (curtm->tm_hour + CCT_DIFF_HOURS) % 24, curtm->tm_min)
/*
current world time :
West time : 11:10
East time : 18:10
*/
return 0;
}
#include
void func(int a) {
{
int a = 4;
printf("-->a=%d\n",a);
}
printf("->a=%d\n",a);
}
int main() {
int a = 1;
{
int a = 2;
printf("-->a=%d\n",a);
}
printf("->a=%d\n",a);
func(3);
return 0;
}
PS D:\jave\Work Files\C\Studies\applied domain> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\applied domain> .\out.exe
-->a=2
->a=1
-->a=4
->a=3
#include
int main() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
const int len = sizeof(arr) / sizeof(int);
printf("len=%d\n", len);
for (int i = 0; i < len; i++)
{
printf("a[%d]=%d\n", i, arr[i]);
}
arr[0] *= 2;
arr[2] *= 2;
arr[4] *= 2;
arr[6] *= 2;
arr[8] *= 2;
printf("\n========= after modify array ==========\n");
int* arr_p = &arr[0];
for (int i = 0; i < len; i++)
{
printf("*arr_p+[%d]=%d\n", i, *(arr_p+i));
}
*(arr_p+1) *= 2;
*(arr_p+3) *= 2;
*(arr_p+5) *= 2;
*(arr_p+7) *= 2;
*(arr_p+9) *= 2;
printf("\n========= after modify pointer ==========\n");
for (int i = 0; i < len; i++)
{
printf("*arr_p+[%d]=%d\n", i, *(arr_p+i));
}
return 0;
}
PS D:\jave\Work Files\C\Studies\1D array test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\1D array test> .\out.exe
len=10
a[0]=1
a[1]=2
a[2]=3
a[3]=4
a[4]=5
a[5]=6
a[6]=7
a[7]=8
a[8]=9
a[9]=10
========= after modify array ==========
*arr_p+[0]=2
*arr_p+[1]=2
*arr_p+[2]=6
*arr_p+[3]=4
*arr_p+[4]=10
*arr_p+[5]=6
*arr_p+[6]=14
*arr_p+[7]=8
*arr_p+[8]=18
*arr_p+[9]=10
========= after modify pointer ==========
*arr_p+[0]=2
*arr_p+[1]=4
*arr_p+[2]=6
*arr_p+[3]=8
*arr_p+[4]=10
*arr_p+[5]=12
*arr_p+[6]=14
*arr_p+[7]=16
*arr_p+[8]=18
*arr_p+[9]=20
#include
#include
typedef struct {
int size;
int * arr;
} ARR_STRUCT;
void printf_element(char* title, int * arr, int size) {
printf("\n%s start\n", title);
for (int i = 0; i < size; i++)
{
printf("%d,", *(arr+i));
}
printf("\n%s end\n", title);
}
void printf_element1(int arr[], int size) {
printf_element("printf_element1", &arr[0], size);
}
ARR_STRUCT GetArr(int size) {
ARR_STRUCT result;
result.size = size;
result.arr = malloc(sizeof(int) * size);
return result;
}
void ResizeArr(ARR_STRUCT* p, int size) {
p->size = size;
realloc(p->arr, size);
}
void FreeArr(ARR_STRUCT v) {
free(v.arr);
}
int main() {
int arr[10][10];
int len2 = sizeof(arr[0]) / sizeof(int);
int len1 = sizeof(arr) / (sizeof(int) * len2);
printf("sizeof(arr) = bytes =%d\n", sizeof(arr));
printf("len1=%d\n", len1);
printf("len2=%d\n", len2);
int idx = 0;
for (int row = 0; row < len1; row++)
{
for (int col = 0; col < len2; col++)
{
arr[row][col] = idx++;
}
}
for (int row = 0; row < len1; row++)
{
printf("row%d:\t", row);
for (int col = 0; col < len2; col++)
{
printf("%d\t", arr[row][col]);
}
printf("\n");
}
printf("======================\n");
int arr2[2][2] = {
{1, 2},
{3, 4}
};
for (int i = 0; i < 2; i++)
{
printf("row%d:\t", i);
for (int j = 0; j < 2; j++)
{
printf("%d\t", arr2[i][j]);
}
printf("\n");
}
printf("======================\n");
int array[9] = {
1, 2, 3,
4, 5, 6,
7, 8, 9
};
int arr3[3][3] = {
1, 2, 3,
4, 5, 6,
7, 8, 9
};
for (int i = 0; i < 3; i++)
{
printf("row%d:\t", i);
for (int j = 0; j < 3; j++)
{
printf("%d\t", arr3[i][j]);
}
printf("\n");
}
printf("======================\n");
int _1D_Arr[3] = {9, 8, 7};
int count = sizeof(_1D_Arr) / sizeof(int);
printf("_1D_Arr count:%d\n",count);
printf("======================\n");
printf("sizeof(array)=%d\n", sizeof(array));
printf_element("printf_element", array, sizeof(array)/sizeof(int));
printf_element1(array, sizeof(array)/sizeof(int));
// printf_element2(array);
printf("======================\n");
ARR_STRUCT arr_struct = GetArr(10);
printf("GetArr start, arr.size=%d\n", arr_struct.size);
for (int i = 0; i < arr_struct.size; i++)
{
*(arr_struct.arr+i) = i*2;
}
for (int i = 0; i < arr_struct.size; i++)
{
printf("%d=%d,",i,*(arr_struct.arr+i));
}
printf("\nGetArr end");
printf("\n======================\n");
printf("Free the array struct\n");
// free(&arr_struct);
FreeArr(arr_struct);
printf("\n======================\n");
printf("\n======================\n");
printf("\nResize start\n");
int resize = 20;
printf("ResizeArr(arr, %d)\n", resize);
// free(&arr_struct);
ResizeArr(&arr_struct, resize);
for (int i = 0; i < arr_struct.size; i++)
{
printf("%d=%d,",i,*(arr_struct.arr+i));
}
for (int i = 0; i < arr_struct.size; i++)
{
*(arr_struct.arr+i) = i;
}
printf("\n");
for (int i = 0; i < arr_struct.size; i++)
{
printf("%d=%d,",i,*(arr_struct.arr+i));
}
resize = 5;
printf("\nResizeArr(arr, %d)\n", resize);
// free(&arr_struct);
ResizeArr(&arr_struct, resize);
for (int i = 0; i < arr_struct.size; i++)
{
printf("%d=%d,",i,*(arr_struct.arr+i));
}
FreeArr(arr_struct);
printf("\nResize end\n");
printf("\n======================\n");
return 0;
}
ve\Work Files\C\Studies\multi D array test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\multi D array test> .\out.exe
sizeof(arr) = bytes =400
len1=10
len2=10
row0: 0 1 2 3 4 5 6 7 8 9
row1: 10 11 12 13 14 15 16 17 18 19
row2: 20 21 22 23 24 25 26 27 28 29
row3: 30 31 32 33 34 35 36 37 38 39
row4: 40 41 42 43 44 45 46 47 48 49
row5: 50 51 52 53 54 55 56 57 58 59
row6: 60 61 62 63 64 65 66 67 68 69
row7: 70 71 72 73 74 75 76 77 78 79
row8: 80 81 82 83 84 85 86 87 88 89
row9: 90 91 92 93 94 95 96 97 98 99
======================
row0: 1 2
row1: 3 4
======================
row0: 1 2 3
row1: 4 5 6
row2: 7 8 9
======================
_1D_Arr count:3
======================
sizeof(array)=36
printf_element start
1,2,3,4,5,6,7,8,9,
printf_element end
printf_element1 start
1,2,3,4,5,6,7,8,9,
printf_element1 end
======================
GetArr start, arr.size=10
0=0,1=2,2=4,3=6,4=8,5=10,6=12,7=14,8=16,9=18,
GetArr end
======================
Free the array struct
======================
======================
Resize start
ResizeArr(arr, 20)
0=11547824,1=11539864,2=4,3=6,4=8,5=10,6=12,7=14,8=16,9=18,10=738197548,11=12476,12=11547824,13=11539864,14=11543720,15=11539880,16=0,17=779384175,18=6649957,19=0,
0=0,1=1,2=2,3=3,4=4,5=5,6=6,7=7,8=8,9=9,10=10,11=11,12=12,13=13,14=14,15=15,16=16,17=17,18=18,19=19,
ResizeArr(arr, 5)
0=0,1=1,2=2,3=3,4=4,
Resize end
======================
#include
typedef enum EnumType {
One = 1,
Two = 2,
ReturnToOne = 1,
Three = 3,
} ET;
int main() {
for (int i = One; i < Three; i++)
{
printf("et:%d,%d\n", i, (ET)i);
}
printf("One==ReturnToOne:%d\n", One==ReturnToOne);
int a = Two;
printf("a=Two,a=%d\n", a);
ET et = 3;
printf("Et et=3,et=%d\n", et);
return 0;
}
PS D:\jave\Work Files\C\Studies\enum test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\enum test> .\out.exe
et:1,1
et:2,2
One==ReturnToOne:1
a=Two,a=2
Et et=3,et=3
#include
#define MODIFY_MEM(offset,type,value) *(type*)(NULL+offset)=value;
#define GET_MEM(offset,type) *(type*)(NULL+offset)
int main() {
int a = 0, b = 0;
printf("int a = 0, b = 0;\n");
printf("a's address : %d bytes\n", &a);
printf("b's address : %d bytes\n", &b);
printf("a'-b'=%d bytes\n", (long)&a-(long)&b);
printf("=================\n");
int arr[2] = {8,2};
printf("int arr[2] = {1,2};\n");
printf("arr[0]'s address : %d bytes\n", &arr[0]);
printf("arr[1]'s address : %d bytes\n", &arr[1]);
printf("arr[0]'-arr[1]'=%d bytes\n", (long)&arr[0]-(long)&arr[1]);
// 可以根据一个int地址,就可以定位内存
long offset = (long)&arr[1];
printf("offset=%d bytes\n", offset);
*(int*)(NULL + offset) = 100; // 直接从NULL(0地址)+偏移定位到指定内存,可以修改对应内存的数据
printf("arr[1]'s address : %d bytes\n", &arr[1]);
printf("arr[1]'s value : %d\n", arr[1]);
MODIFY_MEM(offset, int, 200);
printf("MODIFY_MEM==arr[1]'s address : %d bytes\n", &arr[1]);
printf("MODIFY_MEM==arr[1]'s value : %d\n", arr[1]);
printf("GetMemData==arr[0]==%d\n", GET_MEM((long)&arr[0], int));
printf("=================\n");
int *nullPointer = NULL;
// int *nullPointer = &arr[1];
if(nullPointer) {
printf("nullPointer not NULL\n");
} else {
printf("nullPointer is NULL\n");
}
return 0;
}
PS D:\jave\Work Files\C\Studies\pointer test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\pointer test> .\out.exe
int a = 0, b = 0;
a's address : 6422292 bytes
b's address : 6422288 bytes
a'-b'=4 bytes
=================
int arr[2] = {1,2};
arr[0]'s address : 6422280 bytes
arr[1]'s address : 6422284 bytes
arr[0]'-arr[1]'=-4 bytes
offset=6422284 bytes
arr[1]'s address : 6422284 bytes
arr[1]'s value : 100
MODIFY_MEM==arr[1]'s address : 6422284 bytes
MODIFY_MEM==arr[1]'s value : 200
GetMemData==arr[0]==8
=================
nullPointer is NULL
#include
#include
int main() {
// 设置随机种子
// srand(rand());
for (int i = 0; i < 3; i++)
{
printf("get the %d random number is : %d\n", i, rand());
}
return 0;
}
PS D:\jave\Work Files\C\Studies\rand test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\rand test> .\out.exe
get the 0 random number is : 41
get the 1 random number is : 18467
get the 2 random number is : 6334
#include
// 总和
int sum(int *array, int size) {
int sum = 0;
for (int i = 0; i < size; i++){
sum += *(array+i);
}
return sum;
}
// 平均值
int avg(int *array, int size) {
return (sum(array, size) / size);
}
// 最大值
int max(int *array, int size) {
int max = *array;
for (int i = 1; i < size; i++){
int v = *(array+i);
max = max < v ? v : max;
}
return max;
}
// 最小值
int min(int *array, int size) {
int min = *array;
for (int i = 1; i < size; i++){
int v = *(array+i);
min = min > v ? v : min;
}
return min;
}
// 打印数据
void printArr(char *title, int *array, int size) {
printf("%s", title);
for (int i = 0; i < size; i++){
printf("%d, ", *(array+i));
}
printf("\n");
}
// 对数组数据执行callback来过滤数据的函数
int filterEntry(int (*callback)(int*,int), int *array, int size) {
return callback(array, size);
}
int main() {
int scores[8] = {100, 60, 45, 70, 98, 100, 95, 99};
const int size = sizeof(scores) / sizeof(int);
printArr("score list : ", scores, size);
printf("sum of score list : %d\n", filterEntry(sum, scores, size));
printf("avg of score list : %d\n", filterEntry(avg, scores, size));
printf("max of score list : %d\n", filterEntry(max, scores, size));
printf("min of score list : %d\n", filterEntry(min, scores, size));
return 0;
}
PS D:\jave\Work Files\C\Studies\callback or func pointer test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\callback or func pointer test> .\out.exe
score list : 100, 60, 45, 70, 98, 100, 95, 99,
sum of score list : 667
avg of score list : 83
max of score list : 100
min of score list : 45
#include
#include
// 我们可以自己来编写、测试一个类似strlen的函数
int my_strlen(char* str) {
register int len = 0;
while(*(str+len)!='\0') ++len;
return len;
}
// 注意destination必须为可写缓存
// 如果传入的destination的原始数据是char*是不可修改的常量
// 所以我们的destination只能传入char arr[]数组
char* my_strcpy(char* destination, char* source) {
register int i = 0;
while(*(source+i)!='\0') {
*(destination + i) = *(source + i);
++i;
}
*(destination + i) = '\0'; // 添加会结束符
return destination;
}
// 返回destination + connectingStr
// 注意destination传入的只能是可修改内存
char* my_strcat(char* destination, char* connectingStr) {
register int validatedLen = my_strlen(destination);
register int i = 0;
while(*(connectingStr+i)!='\0') {
*(destination + (validatedLen + i)) = *(connectingStr + i);
++i;
}
*(destination + (validatedLen + i)) = '\0'; // 添加会结束符
return destination;
}
// a > b, reutrn 1;
// a == b, return 0;
// a < b, return -1;
int my_strcmp(char *a, char* b) {
register int aLen = my_strlen(a);
register int bLen = my_strlen(b);
register int minLen = aLen < bLen ? aLen : bLen;
register int aV = 0, bV = 0;
for (register int i = 0; i < minLen; i++) {
aV = *(a + i);
bV = *(b + i);
if (aV > bV) return 1;
else if(aV < bV) return -1;
}
if (aLen > bLen) return 1;
else if (aLen < bLen) return -1;
return 0;
}
// 在str字符串中查找chr字符对应位置的指针
// 查找不到返回NULL
char* my_strchr(char *str, int chr) {
register int validatedLen = my_strlen(str) + 1; // +1因为最后一个'\0'也算入搜索范围
register int i = 0;
do
{
if ((int)*(str + i) == chr) {
return (str + i);
}
++i;
} while (i < validatedLen);
return NULL;
}
// 在str字符串中查找 searchStr 字符对应位置的指针
// 查找不到返回NULL
char* my_strstr(char *str, char *searchStr) {
// if (*(searchStr) == "" || *(searchStr) == "\0") return str;
if (my_strcmp(searchStr, "") == 0 || my_strcmp(searchStr, "\0") == 0) return str;
register int aLen = my_strlen(str);
register int bLen = my_strlen(searchStr);
char same = 0;
char *p = NULL;
for (register int i = 0; i < aLen; i++)
{
same = 1;
p = str + i;
for (register int j = 0; j < bLen; j++)
{
if (*(p + j) != *(searchStr + j)) {
same = 0;
break;
}
}
if (same) return p;
}
return NULL;
}
int main() {
// normally test
char* name = "jave.lin";
printf("A:Jave.Lin, Any you?\n", name);
printf("B:Bill.Gates\n");
char names[20] = "TonyStack";
printf("A:Any other guys..., name?\n");
printf("C:My name is %s...\n", names);
printf("A:OK, Here we go. Changed the world!\n");
printf("====================================\n");
// testing end char '\0'
// and testing sizeof(str_pointer) & sizeof(type) & strlen(str_poinster)
printf("========== testing end char \'\\0\' & strlen & sizeof =============\n");
char content[10] = "123456789";
printf("content=%s, sizeof(content)=%d, strlen(content)=%d\n", content, sizeof(content), strlen(content));
content[3]='\0'; // 将3索引的值设置为'\0',3索引就是第4个
printf("content=%s, sizeof(content)=%d, strlen(content)=%d\n", content, sizeof(content), strlen(content)); // 所以我们只看到输出 "123"
char* str = "aaa"; // 3个a字符
// sizeof(str)==4 说明 一串 "aaa" 中,最后一个字符是'\0',所以是4个字符的大小
// strlen(str)==3 说明它是没有算上'\0'的
printf("str=%s, sizeof(str)==%d, strlen(str)=%d\n", str, sizeof(str), strlen(str));
register int x = 0;
// 注意register沒有RAM地址,他是在CPU上的缓存,所以sizeof计算的是该int值类型的byte占用数量
printf("register int x, sizeof(x) == %d\n", sizeof(x)); // sizeof(x) == 4 (bytes)
long *test;
printf("sizeof(test)==%d\n", sizeof(test));
// 结合上面的sizeof(str), 与strlen(str),可以看到两者区别:
// - sizeof(str) : 计算的是一个 指针地址数据 或是 动态分配的内存对象 或是 数据类型 的大小
// char* str; sizeof(str) == 4 // 计算的是一个 指针地址数据 ,即用于 表示地址数据用的数据类型 通常是int占用4个bytes
// char str[50]; sizeof(str) == 50 // 计算的是 动态分配的内存对象 占用的字节数
// sizeof(long double) == 12 // 计算的是 数据类型 的大小
// - strlen(str) : 计算的是一个 字符串中有效表示出来字符连续大小,就是从字符的0索引到第一个遇到的'\0'字符的数量统计(但不包括'\0')
// strlen(str) 的伪代码如下:
/*
int my_strlen(char* str) {
register int len = 0;
while(*(str+len)!='\0') ++len;
return len;
}
*/
printf("str=%s, sizeof(str)==%d, strlen(str)=%d, my_strlen(str)=%d\n", str, sizeof(str), strlen(str), my_strlen(str));
// testing strcpy
char *str1 = "you are my sun shin";
printf("str1=%s, sizeof(str1)==%d\n", str1, sizeof(str1));
// error testing
// char *str2 = NULL;
// printf("str2=%s\n", str2);
// // 这里注意char *,是常量字符串,在字符表里有记录的,字符指针无法修改内容的,否则会出错
// strcpy(str2, str1);
// printf("str2=%s\n", str2);
// 那么我们只能用char var[]的方式了,这种方式的内存是可以更改的,不是常量字符表的方式
// correct testing
printf("========== testing strcpy =============\n");
char str2[50];
printf("str2=%s, sizeof(str2)==%d\n", str2, sizeof(str2));
// testing strcpy
strcpy(str2, str1);
printf("str2=%s, sizeof(str2)==%d, strlen(str2)==%d, my_strlen(str2)==%d\n",
str2, sizeof(str2), strlen(str2), my_strlen(str2));
// testing strlen & my_strlen, on no end char
char str3[2] = "1";
str3[1] = 'a'; // 我们把尾部的修改了,strlen或是my_strlen就不对了,strlen有可能遍历到别的地址的数据了,直到遇到'\0'
printf("before my_strcpy str2=%s\n", str2);
my_strcpy(str2, "that's my name");
printf("after my_strcpy str2=%s\n", str2);
printf("strlen(str3)=%d, my_strlen(str3)=%d\n", strlen(str3), my_strlen(str3));
// testing strcat
printf("========== testing strcat =============\n");
char a_src[4] = "123";
a_src[1] = '\0'; // 可以把这一句注释掉可以看到
char a[10];
strcpy(a, a_src);
printf("a=%s\n",a);
char *b = "456";
printf("a_src=%s,a=%s,b=%s,strcat(a,b)=%s\n", a_src, a, b, strcat(a,b));
char b_src[7] = "654321";
char b_dest[20] = "123456";
printf("before my_strcat, src=%s, dest=%s\n", b_src, b_dest);
my_strcat(b_dest, b_src);
printf("after my_strcat, src=%s, dest=%s\n", b_src, b_dest);
printf("before my_strcat, src=%s, dest=%s\n", b_src, b_dest);
b_src[3]='\0';
b_dest[3]='\0';
my_strcat(b_dest, b_src);
printf("after my_strcat, src=%s, dest=%s\n", b_src, b_dest);
/*
a_src[1] = '\0'; // 可以把这一句注释掉输出以下结果
a=123
a_src=123,a=123456,b=456,strcat(a,b)=123456
a_src[1] = '\0'; // 运行这一句的话,输出以下结果
a=1
a_src=1,a=1456,b=456,strcat(a,b)=1456
从结果可以看到strcat复制的是0~'\0'之间的字符
*/
// testing strcmp
printf("========== testing strcmp =============\n");
char *cmp_str_1 = "a";
char *cmp_str_2 = "b";
char *cmp_str_3 = "c";
char *cmp_str_4 = "aabb";
char *cmp_str_5 = "aabb";
char *cmp_str_6 = "aabc";
char *cmp_str_7 = "aac";
char *cmp_str_8 = "aa";
char cmp_str_9[3] = "aa";
cmp_str_9[1]='\0';
printf("cmp_str_1=%s,cmp_str_2=%s\n", cmp_str_1, cmp_str_2);
printf("cmp_str_1'ASCII=%d,cmp_str_2'ASCII=%d\n", (int)(*cmp_str_1), (int)(*cmp_str_2));
printf("strcmp(%s, %s)=%d\n",cmp_str_1,cmp_str_2,strcmp(cmp_str_1, cmp_str_2));
printf("strcmp(%s, %s)=%d\n",cmp_str_3,cmp_str_2,strcmp(cmp_str_3, cmp_str_2));
printf("strcmp(%s, %s)=%d\n",cmp_str_4, cmp_str_5,strcmp(cmp_str_4, cmp_str_5));
printf("strcmp(%s, %s)=%d\n",cmp_str_6, cmp_str_5,strcmp(cmp_str_6, cmp_str_5));
printf("strcmp(%s, %s)=%d\n",cmp_str_5, cmp_str_6,strcmp(cmp_str_5, cmp_str_6));
printf("strcmp(%s, %s)=%d\n",cmp_str_6, cmp_str_7,strcmp(cmp_str_6, cmp_str_7));
printf("strcmp(%s, %s)=%d\n",cmp_str_3, cmp_str_7,strcmp(cmp_str_3, cmp_str_7));
printf("strcmp(%s, %s)=%d\n",cmp_str_1, cmp_str_8,strcmp(cmp_str_1, cmp_str_8));
printf("strcmp(%s, %s)=%d\n",cmp_str_1, cmp_str_9,strcmp(cmp_str_1, cmp_str_9));
printf("my_strcmpy start testing\n");
printf("strcmp(%s, %s)=%d\n",cmp_str_1,cmp_str_2,my_strcmp(cmp_str_1, cmp_str_2));
printf("strcmp(%s, %s)=%d\n",cmp_str_3,cmp_str_2,my_strcmp(cmp_str_3, cmp_str_2));
printf("strcmp(%s, %s)=%d\n",cmp_str_4, cmp_str_5,my_strcmp(cmp_str_4, cmp_str_5));
printf("strcmp(%s, %s)=%d\n",cmp_str_6, cmp_str_5,my_strcmp(cmp_str_6, cmp_str_5));
printf("strcmp(%s, %s)=%d\n",cmp_str_5, cmp_str_6,my_strcmp(cmp_str_5, cmp_str_6));
printf("strcmp(%s, %s)=%d\n",cmp_str_6, cmp_str_7,my_strcmp(cmp_str_6, cmp_str_7));
printf("strcmp(%s, %s)=%d\n",cmp_str_3, cmp_str_7,my_strcmp(cmp_str_3, cmp_str_7));
printf("strcmp(%s, %s)=%d\n",cmp_str_1, cmp_str_8,my_strcmp(cmp_str_1, cmp_str_8));
printf("strcmp(%s, %s)=%d\n",cmp_str_1, cmp_str_9,my_strcmp(cmp_str_1, cmp_str_9));
printf("my_strcmpy end testing\n");
/*
输出
cmp_str_1=a,cmp_str_2=b
cmp_str_1'ASCII=97,cmp_str_2'ASCII=98
strcmp(a, b)=-1
strcmp(c, b)=1
strcmp(aabb, aabb)=0
strcmp(aabc, aabb)=1
strcmp(aabb, aabc)=-1
strcmp(aabc, aac)=-1
strcmp(c, aac)=1
从上面的结果可以看出来是遍历字符的ASCII的大小来区别的
如果ASCII都一样,就比较谁的字符比较长
同样也是截取有效字符来比较的
*/
// testing strchr
printf("========== testing strchr =============\n");
char strchr_str1[100] = "this is my testing message";
char strchr_str2[10] = "1234567";
printf("strchr_str1=%s\n", strchr_str1);
char chr = 'y';
printf("strchr_str1'=%d,strchr(%c)'==%d,interval=%d\n",
(int)strchr_str1,
chr,
(int)strchr(strchr_str1, chr),
(int)strchr(strchr_str1, chr)-(int)strchr_str1);
strchr_str1[4]='\0';
printf("after changed strchr_str1'=%d,strchr(%c)'==%d,interval=%d\n",
(int)strchr_str1,
chr,
(int)strchr(strchr_str1, chr),
(int)strchr(strchr_str1, chr)-(int)strchr_str1);
printf("strchr_str2'=%d,strchr(%c)'==%d,interval=%d\n",
(int)strchr_str2,
chr,
(int)strchr(strchr_str2, chr),
(int)strchr(strchr_str2, chr)-(int)strchr_str2);
printf("seach end char strchr_str1'=%d,strchr(%c)'==%d,interval=%d\n",
(int)strchr_str1,
'\0',
(int)strchr(strchr_str1, '\0'),
(int)strchr(strchr_str1, '\0')-(int)strchr_str1);
printf("seach end char strchr_str2'=%d,strchr(%c)'==%d,interval=%d\n",
(int)strchr_str2,
'\0',
(int)strchr(strchr_str2, '\0'),
(int)strchr(strchr_str2, '\0')-(int)strchr_str2);
printf("seach end char in empty str strchr_str2'=%d,strchr(%c)'==%d,interval=%d\n",
(int)"",
'\0',
(int)strchr("", '\0'),
(int)strchr("", '\0')-(int)"");
printf("my_strchr start testing\n");
printf("after changed strchr_str1'=%d,my_strlen(%c)'==%d,interval=%d\n",
(int)strchr_str1,
chr,
(int)my_strchr(strchr_str1, chr),
(int)my_strchr(strchr_str1, chr)-(int)strchr_str1);
printf("strchr_str2'=%d,my_strlen(%c)'==%d,interval=%d\n",
(int)strchr_str2,
chr,
(int)my_strchr(strchr_str2, chr),
(int)my_strchr(strchr_str2, chr)-(int)strchr_str2);
printf("seach end char strchr_str1'=%d,my_strlen(%c)'==%d,interval=%d\n",
(int)strchr_str1,
'\0',
(int)my_strchr(strchr_str1, '\0'),
(int)my_strchr(strchr_str1, '\0')-(int)strchr_str1);
printf("seach end char strchr_str2'=%d,my_strlen(%c)'==%d,interval=%d\n",
(int)strchr_str2,
'\0',
(int)my_strchr(strchr_str2, '\0'),
(int)my_strchr(strchr_str2, '\0')-(int)strchr_str2);
printf("seach end char in empty str strchr_str2'=%d,my_strlen(%c)'==%d,interval=%d\n",
(int)"",
'\0',
(int)my_strchr("", '\0'),
(int)my_strchr("", '\0')-(int)"");
printf("my_strchr end testing\n");
/*
输出结果为
strchr_str1=this is my testing message
strchr_str1'=6422029,strchr(y)'==6422038,interval=9
after changed strchr_str1'=6422029,strchr(y)'==0,interval=-6422029
strchr_str2'=6422019,strchr(y)'==0,interval=-6422019
seach end char strchr_str1'=6422029,strchr( )'==6422033,interval=4
seach end char strchr_str2'=6422019,strchr( )'==6422026,interval=7
seach end char in empty str strchr_str2'=4220380,strchr( )'==4220380,interval=0
my_strchr start testing
after changed strchr_str1'=6422029,my_strlen(y)'==0,interval=-6422029
strchr_str2'=6422019,my_strlen(y)'==0,interval=-6422019
seach end char strchr_str1'=6422029,my_strlen( )'==6422033,interval=4
seach end char strchr_str2'=6422019,my_strlen( )'==6422026,interval=7
seach end char in empty str strchr_str2'=4220380,my_strlen( )'==4220380,interval=0
my_strchr end testing
从输出结果中可以看出:不管搜索的字符串是什么相等就返回对应的索引位置的指针
*/
// testing strstr
printf("========== testing strstr =============\n");
char strstr_str1[100] = "this is my testing message";
char strstr_str2[100] = "this is my testing message";
char searchStr[50] = "testing";
char searchStr1[50] = "testing1";
printf("strstr_str1=%s\n", strstr_str1);
printf("strstr_str1'=%d,strstr(%s)'==%d,interval=%d\n",
(int)strstr_str1,
searchStr,
(int)strstr(strstr_str1, searchStr),
(int)strstr(strstr_str1, searchStr)-(int)strstr_str1);
printf("strstr_str1'=%d,strstr(%s)'==%d,interval=%d\n",
(int)strstr_str1,
searchStr1,
(int)strstr(strstr_str1, searchStr1),
(int)strstr(strstr_str1, searchStr1)-(int)strstr_str1);
searchStr1[1] = 's';
searchStr1[2] = '\0';
printf("strstr_str1'=%d,strstr(%s)'==%d,interval=%d\n",
(int)strstr_str1,
searchStr1,
(int)strstr(strstr_str1, searchStr1),
(int)strstr(strstr_str1, searchStr1)-(int)strstr_str1);
strstr_str1[0]='\0';
searchStr[0] = '\0';
printf("after change strstr_str1'=%d,strstr(%s)'==%d,interval=%d\n",
(int)strstr_str1,
searchStr,
(int)strstr(strstr_str1, searchStr),
(int)strstr(strstr_str1, searchStr)-(int)strstr_str1);
// 下面三个输出一样
printf("after change strstr_str2'=%d,strstr(%s)'==%d,interval=%d\n",
(int)strstr_str2,
"\0",
(int)strstr(strstr_str2, "\0"),
(int)strstr(strstr_str2, "\0")-(int)strstr_str2);
printf("after change strstr_str2'=%d,strstr(%s)'==%d,interval=%d\n",
(int)strstr_str2,
"",
(int)strstr(strstr_str2, ""),
(int)strstr(strstr_str2, "")-(int)strstr_str2);
printf("after change strstr_str2'=%d,strstr(%s)'==%d,interval=%d\n",
(int)strstr_str2,
"t",
(int)strstr(strstr_str2, "t"),
(int)strstr(strstr_str2, "t")-(int)strstr_str2);
printf("my_strstr start testing\n");
// char strstr_str1[100] = "this is my testing message";
// char strstr_str2[100] = "this is my testing message";
// char searchStr[50] = "testing";
// char searchStr1[50] = "testing1";
my_strcpy(strstr_str1, "this is my testing message");
my_strcpy(strstr_str2, "this is my testing message");
my_strcpy(searchStr, "testing");
my_strcpy(searchStr1, "testing1");
printf("strstr_str1=%s\n", strstr_str1);
printf("strstr_str1'=%d,my_strstr(%s)'==%d,interval=%d\n",
(int)strstr_str1,
searchStr,
(int)my_strstr(strstr_str1, searchStr),
(int)my_strstr(strstr_str1, searchStr)-(int)strstr_str1);
printf("strstr_str1'=%d,my_strstr(%s)'==%d,interval=%d\n",
(int)strstr_str1,
searchStr1,
(int)my_strstr(strstr_str1, searchStr1),
(int)my_strstr(strstr_str1, searchStr1)-(int)strstr_str1);
searchStr1[1] = 's';
searchStr1[2] = '\0';
printf("strstr_str1'=%d,my_strstr(%s)'==%d,interval=%d\n",
(int)strstr_str1,
searchStr1,
(int)my_strstr(strstr_str1, searchStr1),
(int)my_strstr(strstr_str1, searchStr1)-(int)strstr_str1);
strstr_str1[0]='\0';
searchStr[0] = '\0';
printf("after change strstr_str1'=%d,my_strstr(%s)'==%d,interval=%d\n",
(int)strstr_str1,
searchStr,
(int)my_strstr(strstr_str1, searchStr),
(int)my_strstr(strstr_str1, searchStr)-(int)strstr_str1);
// 下面三个输出一样
printf("after change strstr_str2'=%d,my_strstr(%s)'==%d,interval=%d\n",
(int)strstr_str2,
"\0",
(int)my_strstr(strstr_str2, "\0"),
(int)my_strstr(strstr_str2, "\0")-(int)strstr_str2);
printf("after change strstr_str2'=%d,my_strstr(%s)'==%d,interval=%d\n",
(int)strstr_str2,
"",
(int)my_strstr(strstr_str2, ""),
(int)my_strstr(strstr_str2, "")-(int)strstr_str2);
printf("after change strstr_str2'=%d,my_strstr(%s)'==%d,interval=%d\n",
(int)strstr_str2,
"t",
(int)my_strstr(strstr_str2, "t"),
(int)my_strstr(strstr_str2, "t")-(int)strstr_str2);
printf("my_strstr start end\n");
/*
输出
strstr_str1=this is my testing message
strstr_str1'=6421919,strstr(testing)'==6421930,interval=11
strstr_str1'=6421919,strstr(testing1)'==0,interval=-6421919
strstr_str1'=6421919,strstr(ts)'==0,interval=-6421919
after change strstr_str1'=6421919,strstr()'==6421919,interval=0
after change strstr_str2'=6421819,strstr()'==6421819,interval=0
after change strstr_str2'=6421819,strstr()'==6421819,interval=0
after change strstr_str2'=6421819,strstr(t)'==6421819,interval=0
my_strstr start testing
strstr_str1=this is my testing message
strstr_str1'=6421919,my_strstr(testing)'==6421930,interval=11
strstr_str1'=6421919,my_strstr(testing1)'==0,interval=-6421919
strstr_str1'=6421919,my_strstr(ts)'==0,interval=-6421919
after change strstr_str1'=6421919,my_strstr()'==6421919,interval=0
after change strstr_str2'=6421819,my_strstr()'==6421819,interval=0
after change strstr_str2'=6421819,my_strstr()'==6421819,interval=0
after change strstr_str2'=6421819,my_strstr(t)'==6421819,interval=0
my_strstr start end
*/
return 0;
}
PS D:\jave\Work Files\C\Studies\string test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\string test> .\out.exe
A:Jave.Lin, Any you?
B:Bill.Gates
A:Any other guys..., name?
C:My name is TonyStack...
A:OK, Here we go. Changed the world!
====================================
========== testing end char '\0' & strlen & sizeof =============
content=123456789, sizeof(content)=10, strlen(content)=9
content=123, sizeof(content)=10, strlen(content)=3
str=aaa, sizeof(str)==4, strlen(str)=3
register int x, sizeof(x) == 4
sizeof(test)==4
str=aaa, sizeof(str)==4, strlen(str)=3, my_strlen(str)=3
str1=you are my sun shin, sizeof(str1)==4
========== testing strcpy =============
str2=, sizeof(str2)==50
str2=you are my sun shin, sizeof(str2)==50, strlen(str2)==19, my_strlen(str2)==19
before my_strcpy str2=you are my sun shin
after my_strcpy str2=that's my name
strlen(str3)=16, my_strlen(str3)=16
========== testing strcat =============
a=1
a_src=1,a=1456,b=456,strcat(a,b)=1456
before my_strcat, src=654321, dest=123456
after my_strcat, src=654321, dest=123456654321
before my_strcat, src=654321, dest=123456654321
after my_strcat, src=654, dest=123654
========== testing strcmp =============
cmp_str_1=a,cmp_str_2=b
cmp_str_1'ASCII=97,cmp_str_2'ASCII=98
strcmp(a, b)=-1
strcmp(c, b)=1
strcmp(aabb, aabb)=0
strcmp(aabc, aabb)=1
strcmp(aabb, aabc)=-1
strcmp(aabc, aac)=-1
strcmp(c, aac)=1
strcmp(a, aa)=-1
strcmp(a, a)=0
my_strcmpy start testing
strcmp(a, b)=-1
strcmp(c, b)=1
strcmp(aabb, aabb)=0
strcmp(aabc, aabb)=1
strcmp(aabb, aabc)=-1
strcmp(aabc, aac)=-1
strcmp(c, aac)=1
strcmp(a, aa)=-1
strcmp(a, a)=0
my_strcmpy end testing
========== testing strchr =============
strchr_str1=this is my testing message
strchr_str1'=6422029,strchr(y)'==6422038,interval=9
after changed strchr_str1'=6422029,strchr(y)'==0,interval=-6422029
strchr_str2'=6422019,strchr(y)'==0,interval=-6422019
seach end char strchr_str1'=6422029,strchr( )'==6422033,interval=4
seach end char strchr_str2'=6422019,strchr( )'==6422026,interval=7
seach end char in empty str strchr_str2'=4223044,strchr( )'==4223044,interval=0
my_strchr start testing
after changed strchr_str1'=6422029,my_strlen(y)'==0,interval=-6422029
strchr_str2'=6422019,my_strlen(y)'==0,interval=-6422019
seach end char strchr_str1'=6422029,my_strlen( )'==6422033,interval=4
seach end char strchr_str2'=6422019,my_strlen( )'==6422026,interval=7
seach end char in empty str strchr_str2'=4223044,my_strlen( )'==4223044,interval=0
my_strchr end testing
========== testing strstr =============
strstr_str1=this is my testing message
strstr_str1'=6421919,strstr(testing)'==6421930,interval=11
strstr_str1'=6421919,strstr(testing1)'==0,interval=-6421919
strstr_str1'=6421919,strstr(ts)'==0,interval=-6421919
after change strstr_str1'=6421919,strstr()'==6421919,interval=0
after change strstr_str2'=6421819,strstr()'==6421819,interval=0
after change strstr_str2'=6421819,strstr()'==6421819,interval=0
after change strstr_str2'=6421819,strstr(t)'==6421819,interval=0
my_strstr start testing
strstr_str1=this is my testing message
strstr_str1'=6421919,my_strstr(testing)'==6421930,interval=11
strstr_str1'=6421919,my_strstr(testing1)'==0,interval=-6421919
strstr_str1'=6421919,my_strstr(ts)'==0,interval=-6421919
after change strstr_str1'=6421919,my_strstr()'==6421919,interval=0
after change strstr_str2'=6421819,my_strstr()'==6421819,interval=0
after change strstr_str2'=6421819,my_strstr()'==6421819,interval=0
after change strstr_str2'=6421819,my_strstr(t)'==6421819,interval=0
my_strstr start end
#include
#include
#include
typedef struct B BType;
typedef struct A {
char name[50];
BType *b_pointer;
} AType;
typedef struct B {
char name[50];
AType *a_pointer;
} BType;
typedef struct C {
int a;
char b;
} CType;
typedef struct BF { // bit-field
// 单计算没有位域的struct的占用byte数量还是比较简单的
// 结构体大小的计算 : https://www.runoob.com/w3cnote/struct-size.html
// CType c;
// 但是一旦加入了bit-field,计算方式就会复杂很多
// char v : 8; // char == 1 byte
// unsigned char v : 8; // unsinged char == 1 byte
// short v : 16; // short == 2 bytes
// unsigned short v : 16; // unsigned short == 2 bytes
// unsigned v : 32; // 无类型,的unsinged 默认为一个int,一个int==4byte
// int v : 32; // 4 bytes
// unsigned int v : 32; // 4 bytes
// long v : 32; // 4 bytes
// unsigned long v : 32; // 4 bytes
// size_t v : 32; // 4 bytes
// 如果一个bit field里包含了各种不一样的数据类型
// 那么将会以 最大的位数 的数据类型来做 对齐
// 下面3个v1,v2,v3定义这个 bit-field的话,需要使用8 bytes,原因下面有些
// char v1 : 1; // 1 byte
// short v2 : 1; // 2 bytes
// int v3 : 1; // 三者中最大为int 4 bytes
// 前面的char和short对齐到一个int里
// 所以这里就相当于用了8个 bytes 来定义一个bit field
// 下面8个f1~f8定义这个 bit-field的话,需要使用1 bytes,原因下面有些
// char f1 : 1;
// char f2 : 1;
// char f3 : 1;
// char f4 : 1;
// char f5 : 1;
// char f6 : 1;
// char f7 : 1;
// char f8 : 1;
// 前面的 8个char 都一样,所以还是对齐到一个char
// 所以这里就相当于用了1个 bytes 来定义一个bit field
// 那么下面这个呢,什么都用一起了
// 我们还最大的是int,unsigned int, long, unsigned long都是4bytes
// 所以最小按4 bytes来对齐
// 有v1~v8个,所以就是,暂时没有发现规律,后面需要再细究
char v1 : 1;
unsigned char v2 : 1;
short v3 : 1;
unsigned short v4 : 1;
int v5 : 1;
unsigned int v6 : 1;
long v7 : 1;
unsigned long v8 : 1;
} BFType;
int main() {
printf("sizeof(AType)==%d,sizeof(BType)==%d\n",sizeof(AType),sizeof(BType));
printf("=====on stack variable testing=====\n");
AType a_struct={"This is A's name", NULL};
BType b_struct={"This is B's name", NULL};
printf("a_struct.name=%s,b_struct.name=%s\n",a_struct.name,b_struct.name);
a_struct.b_pointer = &b_struct;
b_struct.a_pointer = &a_struct;
printf("a_struct=%p,b_struct=%p\n",&a_struct,&b_struct);
printf("a_struct.b_pointer=%p,b_struct.a_pointer=%p\n",
a_struct.b_pointer, b_struct.a_pointer);
strcpy(a_struct.name, "Tom");
strcpy(b_struct.name, "Jerry");
printf("a_struct.name=%s,b_struct.name=%s\n",a_struct.name,b_struct.name);
printf("=====on heap pointer variable testing=====\n");
// 添加指针的struct只能指向一个现有的结构体地址
// 如果不指向现有的地址,那就只能自己创建堆数据来指向它
/*
序号 函数和描述
1 void *calloc(int num, int size);
在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。所以它的结果是分配了 num*size 个字节长度的内存空间,并且每个字节的值都是0。
2 void free(void *address);
该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。
3 void *malloc(int num);
在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。
4 void *realloc(void *address, int newsize);
该函数重新分配内存,把内存扩展到 newsize。
*/
AType *a_pointer = malloc(sizeof(AType));
BType *b_pointer = malloc(sizeof(BType));
strcpy(a_pointer->name,"Bill.Gates");
strcpy(b_pointer->name,"Steven.Jobs");
printf("a_pointer->name=%s,b_struct.name=%s\n",a_pointer->name,b_pointer->name);
a_pointer->b_pointer = b_pointer;
b_pointer->a_pointer = a_pointer;
printf("a_pointer=%p,b_pointer=%p\n",a_pointer,b_pointer);
printf("a_pointer->b_pointer=%p,b_pointer->a_pointer=%p\n",
a_pointer->b_pointer, b_pointer->a_pointer);
printf("free the pointers\n");
free(a_pointer);
free(b_pointer);
// 这里free了之后还可以使用
printf("after free a_pointer=%p,b_pointer=%p\n",a_pointer,b_pointer);
strcpy(a_pointer->name,"1");
strcpy(b_pointer->name,"2");
printf("after free a_pointer->name=%s,b_struct.name=%s\n",a_pointer->name,b_pointer->name);
// 所以我们最好养成习惯free了之后的heap数据都指向NULL
a_pointer = NULL;
b_pointer = NULL;
// 这时输出地址就变成00000000了
printf("after free a_pointer=%p,b_pointer=%p\n",a_pointer,b_pointer);
// 如果恢复下面对NULL数据的->name就会报错
// strcpy(a_pointer->name,"1");
// strcpy(b_pointer->name,"2");
printf("sizeof(unsigned)==%d\n", sizeof(unsigned)); // 4
printf("sizeof(unsigned int)==%d\n", sizeof(unsigned int)); // 4
printf("sizeof(unsigned long)==%d\n", sizeof(unsigned long)); // 4
printf("sizeof(long int)==%d\n", sizeof(long int)); // 4
printf("sizeof(unsigned long int)==%d\n", sizeof(unsigned long int)); // 4
printf("sizeof(long double)==%d\n", sizeof(long double)); // 12
printf("sizeof(double)==%d\n", sizeof(double)); // 8
// bit field testing
printf("=====bit field testing=====\n");
BFType bf = {1,1,1,1,1,1,1,1};
printf("sizeof(BFType)==%d\n",sizeof(BFType));
printf("sizeof(bf)==%d\n",sizeof(bf));
printf("bf.v1=%d\n",bf.v1);
printf("bf.v2=%d\n",bf.v2);
printf("bf.v3=%d\n",bf.v3);
printf("bf.v4=%d\n",bf.v4);
printf("bf.v5=%d\n",bf.v5);
printf("bf.v6=%d\n",bf.v6);
printf("bf.v7=%d\n",bf.v7);
printf("bf.v8=%d\n",bf.v8);
/*
sizeof(BFType)==8
sizeof(bf)==8
bf.v1=-1
bf.v2=1
bf.v3=-1
bf.v4=1
bf.v5=-1
bf.v6=1
bf.v7=-1
bf.v8=1
因为有些只剩一个符号位了,所以就是-1,
所以一般只有1 bit的,一般用无符号来表示,结果就是0或是1
*/
printf("done!\n");
return 0;
}
PS D:\jave\Work Files\C\Studies\struct test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\struct test> .\out.exe
sizeof(AType)==56,sizeof(BType)==56
=====on stack variable testing=====
a_struct.name=This is A's name,b_struct.name=This is B's name
a_struct=0061FEE0,b_struct=0061FEA8
a_struct.b_pointer=0061FEA8,b_struct.a_pointer=0061FEE0
a_struct.name=Tom,b_struct.name=Jerry
=====on heap pointer variable testing=====
a_pointer->name=Bill.Gates,b_struct.name=Steven.Jobs
a_pointer=00C022D8,b_pointer=00C02318
a_pointer->b_pointer=00C02318,b_pointer->a_pointer=00C022D8
free the pointers
after free a_pointer=00C022D8,b_pointer=00C02318
after free a_pointer->name=1,b_struct.name=2
after free a_pointer=00000000,b_pointer=00000000
sizeof(unsigned)==4
sizeof(unsigned int)==4
sizeof(unsigned long)==4
sizeof(long int)==4
sizeof(unsigned long int)==4
sizeof(long double)==12
sizeof(double)==8
=====bit field testing=====
sizeof(BFType)==8
sizeof(bf)==8
bf.v1=-1
bf.v2=1
bf.v3=-1
bf.v4=1
bf.v5=-1
bf.v6=1
bf.v7=-1
bf.v8=1
done!
#include
typedef struct S1 {
char v1;
char v2;
} S1Type;
typedef struct S2 {
char v1;
char v2;
short v3;
int v4;
} S2Type;
typedef struct S3 {
char v1;
short v3;
char v2;
int v4;
} S3Type;
typedef union U1 {
char v1;
} U1Type;
typedef union U2 {
char v1;
short v2;
} U2Type;
typedef union U3 {
char v1;
short v2;
unsigned v3;
} U3Type;
typedef union U4 {
char v1;
short v2;
unsigned v3;
double v4;
} U4Type;
typedef union U5 {
char v1;
short v2;
unsigned v3;
double v4;
long double v5;
} U5Type;
typedef union U6 {
char v1;
U1Type v2;
S1Type v3;
} U6Type;
typedef union U7 {
char v1;
S2Type v2;
} U7Type;
typedef union U8 {
char v1;
S3Type v2;
} U8Type;
typedef union U9 {
char v1;
char v2[20];
double v3;
// sizeof(char) == 1 && sizeof(double) == 8 : S
// 以最大double 8 bytes对齐
// max(sizeof(v1), sizeof(v2), sizeof(v3)) == 20 : M
// sizeof(U9Type):
// == ((int)(M / S) + (S % M != 0 ? 1 : 0)) * S
// == ((int)(20 / 8) + (8 % 20 != 0 ? 1 : 0)) * 8
// == ( 2 + ( 4 != 0 ? 1 : 0)) * 8
// == ( 2 + ( 1 )) * 8
// == ( 3 ) * 8
// == 3 * 8 = 24
} U9Type;
int main() {
printf("sizeof(U1)==%d\n",sizeof(U1Type));
printf("sizeof(U2)==%d\n",sizeof(U2Type));
printf("sizeof(U3)==%d\n",sizeof(U3Type));
printf("sizeof(U4)==%d\n",sizeof(U4Type));
printf("sizeof(U5)==%d\n",sizeof(U5Type));
printf("sizeof(U6)==%d\n",sizeof(U6Type));
printf("sizeof(U7)==%d\n",sizeof(U7Type));
printf("sizeof(U8)==%d\n",sizeof(U8Type));
printf("sizeof(U9)==%d\n",sizeof(U9Type));
return 0;
}
PS D:\jave\Work Files\C\Studies\union test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\union test> .\out.exe
sizeof(U1)==1
sizeof(U2)==2
sizeof(U3)==4
sizeof(U4)==8
sizeof(U5)==16
sizeof(U6)==2
sizeof(U7)==8
sizeof(U8)==12
sizeof(U9)==24
#include
#include
int main() {
pr intf("Enter a char, please : ");
char c = getchar(); // 只会取第一次输入的字符
// printf("\n");
printf("I got it, you enter the char is : %c\n", c);
printf("putchar(c):");
putchar(c);
printf("\n");
return 0;
}
PS D:\jave\Work Files\C\Studies\stdio test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\stdio test> .\out.exe
Enter a char, please : j
I got it, you enter the char is : j
putchar(c):j
#include
#include
int main() {
char msg[100];
printf("Enter a message again please : (limit 100 chars)");
gets(msg);
printf("I got your message : ");
puts(msg);
printf("\n");
return 0;
}
PS D:\jave\Work Files\C\Studies\stdio test> gcc .\b.c -o out
PS D:\jave\Work Files\C\Studies\stdio test> .\out.exe
Enter a message again please : (limit 100 chars)this is message.
I got your message : this is message.
#include
#include
int main() {
char msg[100];
printf("Enter a message please : (limit 100 chars, split by space)");
scanf("%s", msg);
printf("I got your message : %s\n", msg);
return 0;
}
PS D:\jave\Work Files\C\Studies\stdio test> gcc .\c.c -o out
PS D:\jave\Work Files\C\Studies\stdio test> .\out.exe
Enter a message please : (limit 100 chars, split by space)first second thrid
I got your message : first
先在创建tmp目录
/*
C 文件读写
https://www.runoob.com/cprogramming/c-file-io.html
*/
#include
#include
#include
int main() {
FILE *fp = NULL;
char *filename = "D:\\jave\\Work Files\\C\\Studies\\file io test\\tmp\\test.txt";
fp = fopen(filename, "a+");
char *inputStr = malloc(255);
printf("reading the file info:...\n");
while(fgets(inputStr, 255, (FILE*)fp) > 0) {
printf(inputStr);
Sleep(50);
}
printf("reading complete!\n");
// fprintf(fp, "This is testing for fprintf...\n");
// fputs("This is testing for fputs...\n", fp);
printf("input you want to written message : ");
gets(inputStr); // 输入:#clear,可以执行清空文件命令
if (*inputStr == '#') {
printf("->enter the cmd : ...\n");
if (strcmp((inputStr + 1),"clear")==0) {
printf("cmd:clear action ...");
fclose(fp);
fp = fopen(filename, "w+");
printf("cmd clear action complete!\n");
} else {
printf("unhandle cmd : %s\n", (inputStr + 1));
}
printf("<-exit the cmd.\n");
} else {
fputs(strcat(inputStr, "\n"), fp);
}
free(inputStr);
fclose(fp);
printf("done!\n");
return 0;
}
PS D:\jave\Work Files\C\Studies\file io test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\file io test> .\out.exe
reading the file info:...
new message input
second message.
reading complete!
input you want to written message : last on message
done!
PS D:\jave\Work Files\C\Studies\file io test> .\out.exe
reading the file info:...
new message input
second message.
last on message
reading complete!
input you want to written message : #clear
->enter the cmd : ...
cmd:clear action ...cmd clear action complete!
<-exit the cmd.
done!
PS D:\jave\Work Files\C\Studies\file io test> .\out.exe
reading the file info:...
reading complete!
input you want to written message : new one message
done!
PS D:\jave\Work Files\C\Studies\file io test> .\out.exe
reading the file info:...
new one message
reading complete!
int a_header_file_def_var = 999;
char* a_header_file_def_string = "Hello world!";
void* (*callback)(int,int);
#include // , search in system directory
#include "a.h" // "custom header file", search in custom directory
#define MY_NAME "Jave.Lin" // mapping a string
#define ONE 1 // mapping a number
#define PI 3.14159265359 // mapping pi value
#define UN_DEF_TAG
#undef UN_DEF_TAG
#define STR(v) (#v)
#define SAY_HI_TO(v) ("Hi " #v) // 字符串连接
#define GET_GLOBAL_STR(v) (global_var_##v) // 变量名拼接
#define SUM(a,b) ((a)+(b)) // 求和
#define P(msg) \ // 打印
printf(""#msg "\n")
// 搜索字符
#define SEARCH(str,c,out_idx)\
size_t out_idx=0;\
while (*(str+out_idx)!='\0') {\
if(*(str+out_idx)==c) break;\
++out_idx;\
}\
char * global_var_a = "A STRING CONTENT";
char * global_var_b = "B STRING CONTENT";
char * global_var_c = "B STRING CONTENT";
int sum(int a, int b) {
return a+b;
}
int main() {
// setups...
callback = (void *)sum;
// printf...
printf("Hello %s\n",MY_NAME);
printf("ONE:%d\n",ONE);
printf("ONE:%d\n",ONE);
printf("PI:%d\n",PI);
printf("int_var:%d\n",a_header_file_def_string);
printf("str_var:%s\n",a_header_file_def_string);
printf("callback(%d,%d)==%d\n", 7, 3, callback(7, 3));
#ifdef UN_DEF_TAG
printf("def UN_DEF_TAG\n");
#else
printf("un def UN_DEF_TAG\n");
#endif
#ifndef UN_DEF_TAG
#define UN_DEF_TAG
#endif
#ifdef UN_DEF_TAG
printf("again def UN_DEF_TAG\n");
#else
printf("again un def UN_DEF_TAG\n");
#endif
printf("%s\n", SAY_HI_TO(Bill.Gates));
printf("%s\n", SAY_HI_TO(Steven.Jobs));
printf("input:%s, get the:%s\n", STR(a), GET_GLOBAL_STR(a));
printf("input:%s, get the:%s\n", STR(b), GET_GLOBAL_STR(b));
printf("input:%s, get the:%s\n", STR(c), GET_GLOBAL_STR(c));
#ifndef UN_DEF_TAG
#error have an error...
#endif
#pragma abcdefg
printf("SUM(%d,%d)==%d\n", 70, 30, SUM(70, 30));
printf("__DATE__:%s\n",__DATE__);
printf("__TIME__:%s\n",__TIME__);
printf("__FILE__:%s\n",__FILE__);
printf("__LINE__:%d\n",__LINE__);
printf("__STDC__:%d\n",__STDC__);
P(God Like);
char* content = "123456789A987654321";
char search_c = 'A';
SEARCH(content, search_c, idx)
printf("SEARCH(%s, %c, idx),idx=%d\n",content,search_c,idx);
return 0;
}
PS D:\jave\Work Files\C\Studies\pre-process test> gcc .\a.c -o out PS D:\jave\Work Files\C\Studies\pre-process test> .\out.exe Hello Jave.Lin
ONE:1
ONE:1
PI:1413754602
int_var:4214856
str_var:Hello world!
callback(7,3)==10
un def UN_DEF_TAG
again def UN_DEF_TAG
Hi Bill.Gates
Hi Steven.Jobs
input:a, get the:A STRING CONTENT
input:b, get the:B STRING CONTENT
input:c, get the:B STRING CONTENT
SUM(70,30)==100
__DATE__:Apr 20 2020
__TIME__:10:45:14
__FILE__:.\a.c
__LINE__:86
__STDC__:1
God Like
SEARCH(123456789A987654321, A, idx),idx=9
有三个文件 a.c, a.h, b.h
/*a.c*/
#include "a.h"
int main() {
ap();
bp();
return 0;
}
/*a.h*/
// #include "b.h" // a.h 和 b.h 相互引用会出问题
// 改成条件编译来include
#ifndef __A_H
#define __A_H
#include "b.h"
#endif
int a_var = 1;
void ap() { a_var = b_var; }
/*b.h*/
// #include "a.h" // a.h 和 b.h 相互引用会出问题
#ifndef __B_H
#define __B_H
#include "a.h" // a.h处理了,这里就不用处理了
#endif
int b_var = 2;
void bp() { a_var = 3; }
直接编译报错
PS D:\jave\Work Files\C\Studies\19 include test> gcc .\a.c -o out
In file included from .\b.h:5,
from .\a.h:6,
from .\a.c:2:
.\a.h: In function 'ap':
.\a.h:9:21: error: 'b_var' undeclared (first use in this function); did you mean 'a_var'?
9 | void ap() { a_var = b_var; }
| ^~~~~
| a_var
.\a.h:9:21: note: each undeclared identifier is reported only once for each function it appears in
In file included from .\a.c:2:
.\a.h: At top level:
.\a.h:8:5: error: redefinition of 'a_var'
8 | int a_var = 1;
| ^~~~~
In file included from .\b.h:5,
from .\a.h:6,
from .\a.c:2:
.\a.h:8:5: note: previous definition of 'a_var' was here
8 | int a_var = 1;
| ^~~~~
In file included from .\a.c:2:
.\a.h:9:6: error: redefinition of 'ap'
9 | void ap() { a_var = b_var; }
| ^~
In file included from .\b.h:5,
from .\a.h:6,
from .\a.c:2:
.\a.h:9:6: note: previous definition of 'ap' was here
9 | void ap() { a_var = b_var; }
| ^~
现在 a.c
文件同目录下创建 tmp.txt
PS D:\jave\Work Files\C\Studies\19 include test> gcc -E .\a.c > tmp.txt
查看 tmp.txt
# 1 ".\\a.c"
# 1 ""
# 1 ""
# 1 ".\\a.c"
# 1 ".\\a.h" 1
# 1 ".\\b.h" 1
# 1 ".\\a.h" 1
int a_var = 1;
void ap() { a_var = b_var; }
# 6 ".\\b.h" 2
int b_var = 2;
void bp() { a_var = 3; }
# 7 ".\\a.h" 2
int a_var = 1;
void ap() { a_var = b_var; }
# 3 ".\\a.c" 2
int main() {
ap();
bp();
return 0;
}
可以看到ap() 函数在使用b_var时,b_var的定义还没有被include
/*a.c*/
#include "a.h"
#include "b.h"
int main() {
ap();
bp();
return 0;
}
/*a.h*/
#include "global.h"
void ap() {
a_var = b_var;
}
/*b.h*/
#include "global.h"
void bp() {
a_var = 3;
}
/*global.h*/
int a_var = 1;
int b_var = 2;
编译报错,有重复定义
PS D:\jave\Work Files\C\Studies\19 include test> gcc .\a.c -o out
In file included from .\b.h:2,
from .\a.c:3:
.\global.h:2:5: error: redefinition of 'a_var'
2 | int a_var = 1;
| ^~~~~
In file included from .\a.h:4,
from .\a.c:2:
.\global.h:2:5: note: previous definition of 'a_var' was here
2 | int a_var = 1;
| ^~~~~
In file included from .\b.h:2,
from .\a.c:3:
.\global.h:3:5: error: redefinition of 'b_var'
3 | int b_var = 2;
| ^~~~~
In file included from .\a.h:4,
from .\a.c:2:
.\global.h:3:5: note: previous definition of 'b_var' was here
3 | int b_var = 2;
| ^~~~~
我们用gcc -E再看看预处理内容
PS D:\jave\Work Files\C\Studies\19 include test> gcc -E .\a.c > tmp.txt
打开tmp.txt
# 1 ".\\a.c"
# 1 ""
# 1 ""
# 1 ".\\a.c"
# 1 ".\\a.h" 1
# 1 ".\\global.h" 1
int a_var = 1;
int b_var = 2;
# 3 ".\\a.h" 2
void ap() {
a_var = b_var;
}
# 3 ".\\a.c" 2
# 1 ".\\b.h" 1
# 1 ".\\global.h" 1
int a_var = 1;
int b_var = 2;
# 3 ".\\b.h" 2
void bp() {
a_var = 3;
}
# 4 ".\\a.c" 2
int main() {
ap();
bp();
return 0;
}
可以看到,a_var与b_var有两份定义。
因为我们在a.c引用了"a.h"和"b.h"导致的
我们只更改"a.h","b.h"两个文件就好
/*a.h*/
#ifndef __G_H
#define __G_H
#include "global.h"
#endif
void ap() {
a_var = b_var;
}
/*b.h*/
#ifndef __G_H
#define __G_H
#include "global.h"
#endif
void bp() {
a_var = 3;
}
再来编译,发现没有报错了
再用gcc -E看看预处理结果
# 1 ".\\a.c"
# 1 ""
# 1 ""
# 1 ".\\a.c"
# 1 ".\\a.h" 1
# 1 ".\\global.h" 1
int a_var = 1;
int b_var = 2;
# 5 ".\\a.h" 2
void ap() {
a_var = b_var;
}
# 3 ".\\a.c" 2
# 1 ".\\b.h" 1
void bp() {
a_var = 3;
}
# 4 ".\\a.c" 2
int main() {
ap();
bp();
return 0;
}
可以看到没有重复的a_var,b_var的定义了
#include
#include
#include
#include
extern int errno; // 引入errno.h内的errno变量声明
int main() {
// errno, perror(), strerror() test
// errno == get the error number
// perror(char* title) == print the error with prefix title
// strerror(int errorNumber) == get description of the error number
// ==== open file error test =====
printf("====== open file start test ======\n");
FILE* fp;
int errnum;
fp = fopen("un exsit file.txt","rb");
if (fp == NULL) {
errnum = errno;
fprintf(stderr, "error number : %d\n", errnum);
perror("this is error lable");
fprintf(stderr, "open file error : %s\n", strerror(errno));
} else {
fclose(fp);
}
printf("====== div zero start test ======\n");
int dn = 0;
int n = 1;
// n = n / dn;
// errnum = errno;
if (dn == 0) {
char* strFormat = (char*)malloc(100);
sprintf(strFormat, "May div zero err, dn=%d, n=%d\n", dn, n);
printf(strFormat);
free(strFormat);
exit(-1); // exit by error code : -1
}
printf("done!\n");
return 0;
}
PS D:\jave\Work Files\C\Studies\error print test> gcc .\a.c -o out PS D:\jave\Work Files\C\Studies\error print test> .\out.exe ====== open file start test ======
error number : 2
this is error lable: No such file or directory
open file error : No such file or directory
====== div zero start test ======
May div zero err, dn=0, n=1
#include
#include
#include
#include
#define P_FIXED_SIZE(func_name,arg_num,sizePerArg)\
size_t sizePerArg = sizeof(arg_num);\
printf(#func_name ", have %d dynamic args, " #sizePerArg "=%d\n",arg_num,sizePerArg);
#define P_NO_FIXED_SIZE(func_name)\
printf(#func_name ", have no fixed dynamic args\n");
void func1(char argNum, ...) {
P_FIXED_SIZE(func1, argNum, sizePerArg);
}
void func2(int argNum, ...) {
P_FIXED_SIZE(func2, argNum, sizePerArg);
// 利用从右往左入栈的特性
// 先入栈的地址高
// 所以firstArg是最左边的,从地址底的往高的遍历
int *firstArg = &argNum;
for (int i = 1; i < argNum + 1; i++) {
printf("dynamic arg %d == %d\n", i, *(firstArg + i));
}
}
int func3(char* firstArg,...) {
P_NO_FIXED_SIZE(func3);
/*
需要 #include
va_list,参数列表管理指针,需要用:va_start(list, first)来指定
va_start,用来指定参数列表的首地址:va_start(list, first)
va_arg,在va_list中获取下一个参数:nextArg = va_arg(list, type)
va_end,结果处理,与va_start配对使用:va_end(list)
*/
// 统计参数数量
register int argCounter = 0;
printf("arg %d = %s\n", ++argCounter, firstArg);
// typedef char* va_list;
va_list arglist;
char *getArg;
va_start(arglist, firstArg);
register int i = 255;
while(--i > 0) {
getArg = va_arg(arglist, char*);
if (strcmp(getArg, "") == 0)
break;
printf("arg %d = %s\n", ++argCounter, getArg);
}
va_end(arglist);
if (i < 0) {
printf("func3 over loop, i:%d\n", i);
return -1;
}
return 0;
}
typedef struct Info {
char* name;
int value;
} InfoType;
void SetInfo(InfoType* info, char *name, int value) {
info->name = name;
info->value = value;
}
InfoType* GetInfo(char *name, int value) {
InfoType *result = malloc(sizeof(InfoType));
SetInfo(result, name, value);
return result;
}
void ToStr(InfoType* info, char* str) {
sprintf(str, "name=%s,value=%d", info->name,info->value);
}
int func4(InfoType* firstArg,...) {
P_NO_FIXED_SIZE(func4);
// 统计参数数量
register int argCounter = 0;
char* printStr = malloc(100);
ToStr(firstArg, printStr);
printf("arg %d = %s\n", ++argCounter, printStr);
va_list arglist;
InfoType *getArg;
va_start(arglist, firstArg);
register int i = 255;
while(--i > 0) {
getArg = va_arg(arglist, InfoType*);
if (getArg->value == 0)
break;
ToStr(getArg, printStr);
printf("arg %d = %s\n", ++argCounter, printStr);
}
free(printStr);
va_end(arglist);
if (i < 0) {
printf("func4 over loop, i:%d\n", i);
return -1;
}
return 0;
}
int main() {
func1(2,3,5);
func2(3,1,3,5);
func3("first", "second", "third", "fourth", "");
InfoType* p1 = GetInfo("Bill.Gates", 18);
InfoType* p2 = GetInfo("Steven.Jobs", 17);
InfoType* p3 = GetInfo("Human", 1);
InfoType* p4 = GetInfo("God", 0);
func4(p1,p2,p3,p4);
return 0;
}
PS D:\jave\Work Files\C\Studies\21 dynamic arg num test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\21 dynamic arg num test> .\out.exe
>>
func1, have 2 dynamic args, sizePerArg=1
func2, have 3 dynamic args, sizePerArg=4
dynamic arg 1 == 1
dynamic arg 2 == 3
dynamic arg 3 == 5
func3, have no fixed dynamic args
arg 1 = first
arg 2 = second
arg 3 = third
arg 4 = fourth
func4, have no fixed dynamic args
arg 1 = name=Bill.Gates,value=18
arg 2 = name=Steven.Jobs,value=17
arg 3 = name=Human,value=1
#include
void func(int a, int b, int c) {
int d = 7; // 0061FEFC
double e = 999.9999; // 0061FEF0
int f = 888; // 0061FEEC
int g = 777; // 0061FEE8
int h = 666; // 0061FEE4
int i = 666; // 0061FEE0
int j[2] = {555}; // 1:0061FEDC,0:0061FED8
// params variables
// a~c 地址越来越大,越大的地址,是越早如栈的
// 参数从右往左入栈
printf("a=%p\n",&a);
printf("b=%p\n",&b);
printf("c=%p\n",&c);
// local variables
// h~d 地址越来越大,越大的地址,是越早如栈的
// 参数从下往上入栈
// j数据第1索引的地址比第0索引地址要大
printf("j=%p\n",&j[0]);
printf("i=%p\n",&i);
printf("h=%p\n",&h);
printf("g=%p\n",&g);
printf("f=%p\n",&f);
printf("e=%p\n",&e);
printf("d=%p\n",&d);
}
int main() {
func(1,3,5);
return 0;
}
PS D:\jave\Work Files\C\Studies\22 func variables heap enqueue test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\22 func variables heap enqueue test> .\out.exe
a=0061FF10
b=0061FF14
c=0061FF18
j=0061FED8
i=0061FEE0
h=0061FEE4
g=0061FEE8
f=0061FEEC
e=0061FEF0
d=0061FEFC
#include
#include
void printBuff(char* buff, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%d,", *(buff + i));
}
printf("\n");
}
int main() {
printf("====== malloc start test ======\n");
char* buff = malloc(10);
printf("after malloc buff : ");
printBuff(buff, 10); // malloc 后的指针数据是不确定的
printf("====== free start test ======\n");
free(buff);
printf("after free buff : ");
printBuff(buff, 10);
printf("====== calloc start test ======\n");
buff = calloc(10, sizeof(char));
printf("after calloc buff : "); // calloc 后的指针数据是确定为0的
printBuff(buff, 10);
free(buff);
printf("after free buff : ");
printBuff(buff, 10);
printf("====== realloc start test ======\n");
realloc(buff, 15);
printf("after realloc buff : "); // realloc与malloc一样 指针数据是不确定的
printBuff(buff, 10);
free(buff);
printf("after free buff : ");
printBuff(buff, 10);
return 0;
}
PS D:\jave\Work Files\C\Studies\22 mem mgr test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\22 mem mgr test> .\out.exe
>> ====== malloc start test ======
after malloc buff : -40,34,-78,0,-64,0,-78,0,2,0,
====== free start test ======
after free buff : -40,34,-78,0,-64,0,-78,0,2,0,
====== calloc start test ======
after calloc buff : 0,0,0,0,0,0,0,0,0,0,
after free buff : -40,34,-78,0,-64,0,-78,0,0,0,
====== realloc start test ======
after realloc buff : -40,34,-78,0,-64,0,-78,0,0,0,
after free buff : -40,34,-78,0,-64,0,-78,0,0,0,
#include
#include
#include
// 我们可以自己来编写、测试一个类似strlen的函数
int my_strlen(char* str) {
register int len = 0;
while(*(str+len)!='\0') ++len;
return len;
}
// 注意destination必须为可写缓存
// 如果传入的destination的原始数据是char*是不可修改的常量
// 所以我们的destination只能传入char arr[]数组
char* my_strcpy(char* destination, char* source) {
register int i = 0;
while(*(source+i)!='\0') {
*(destination + i) = *(source + i);
++i;
}
*(destination + i) = '\0'; // 添加会结束符
return destination;
}
// 返回destination + connectingStr
// 注意destination传入的只能是可修改内存
char* my_strcat(char* destination, char* connectingStr) {
register int validatedLen = my_strlen(destination);
register int i = 0;
while(*(connectingStr+i)!='\0') {
*(destination + (validatedLen + i)) = *(connectingStr + i);
++i;
}
*(destination + (validatedLen + i)) = '\0'; // 添加会结束符
return destination;
}
// a > b, reutrn 1;
// a == b, return 0;
// a < b, return -1;
int my_strcmp(char *a, char* b) {
register int aLen = my_strlen(a);
register int bLen = my_strlen(b);
register int minLen = aLen < bLen ? aLen : bLen;
register int aV = 0, bV = 0;
for (register int i = 0; i < minLen; i++) {
aV = *(a + i);
bV = *(b + i);
if (aV > bV) return 1;
else if(aV < bV) return -1;
}
if (aLen > bLen) return 1;
else if (aLen < bLen) return -1;
return 0;
}
// 在str字符串中查找chr字符对应位置的指针
// 查找不到返回NULL
char* my_strchr(char *str, int chr) {
register int validatedLen = my_strlen(str) + 1; // +1因为最后一个'\0'也算入搜索范围
register int i = 0;
do
{
if ((int)*(str + i) == chr) {
return (str + i);
}
++i;
} while (i < validatedLen);
return NULL;
}
// 在str字符串中查找 searchStr 字符对应位置的指针
// 查找不到返回NULL
char* my_strstr(char *str, char *searchStr) {
// if (*(searchStr) == "" || *(searchStr) == "\0") return str;
if (my_strcmp(searchStr, "") == 0 || my_strcmp(searchStr, "\0") == 0) return str;
register int aLen = my_strlen(str);
register int bLen = my_strlen(searchStr);
char same = 0;
char *p = NULL;
for (register int i = 0; i < aLen; i++)
{
same = 1;
p = str + i;
for (register int j = 0; j < bLen; j++)
{
if (*(p + j) != *(searchStr + j)) {
same = 0;
break;
}
}
if (same) return p;
}
return NULL;
}
#define NEW(type) (malloc(sizeof(type)))
#define NEW_MULTI(type,count) (malloc(sizeof(type)*(count)))
// 申请字符串空间,并将src复制到dest
char* my_alloc_cpy_str(char* dest, char* src) {
printf("ac src:%s,",src);
int len = my_strlen(src) + 1; // +1是为了尾部添加'\0'
printf("src's len:%d,",len);
dest = NEW_MULTI(char,len);
my_strcpy(dest, src);
printf("copy to dest, dest:%s\n",dest);
return dest;
}
// 从 src 字符串中获取指定:开始位置,到,结束位置,的字符串,并复制到 dest
// 如果 endIdx == -1,则截取到尾部的字符,截取的字符中不包含 第endIdx个字符
char* my_alloc_get_str(char* dest, char* src, int startIdx, int endIdx, char forceNew) {
if (endIdx == -1) {
endIdx = my_strlen(src);
printf("endIdx == -1, changed to : %d\n", endIdx);
}
if (endIdx < startIdx) {
printf("endIdx < startIdx\n");
return dest;
}
if (endIdx == startIdx) {
printf("endIdx == startIdx\n");
return dest;
}
printf("--->split src:%s,start:%d,end:%d\n",src,startIdx,endIdx);
int len = endIdx - startIdx;
if (!dest || forceNew) {
dest = NEW_MULTI(char, len + 1); // +1因为要有结束符
}
printf("start:%d,end:%d->",startIdx,endIdx);
for (size_t i = 0, srcOffset = startIdx; srcOffset < endIdx; srcOffset++, i++) {
printf("%d:%c,",srcOffset,*(src + srcOffset));
*(dest + i) = *(src + srcOffset);
}
printf("\n");
// 补上结束符
*(dest + len) = '\0';
return dest;
}
typedef struct Arg {
char* name;
char* value;
} ArgType;
typedef struct ArgNode ArgNodeType;
typedef struct ArgNode {
ArgType* arg;
ArgNodeType* next;
} ArgNodeType;
ArgType* get_args(int argc, char* args[], const char spliter) {
int spliterPos;
char* spliterPosPointer;
ArgNodeType* firstNode = NULL;
ArgNodeType* curNodeArg = NULL;
ArgType* newArg = NULL;
// 忽略第一个参数
for (size_t i = 1; i < argc; i++) {
char* a = args[i];
// 第一次检测
ArgType* arg = NULL;
spliterPosPointer = my_strchr(a, spliter);
if (spliterPosPointer) { // 有分隔符
char* errorPointer = my_strchr(spliterPosPointer + 1, spliter);
if (errorPointer) { // 第二次还有重复的分隔符
printf("error: multi spliter char, arg[%d]=%s\n", i, a);
return NULL;
}
spliterPos = (int)spliterPosPointer - (int)a;
// printf("spliterPos==%d\n", spliterPos);
if (spliterPos == 0) {
printf("error: split char position invalidated, arg[%d]=%s\n", i, a);
return NULL;
}
arg = NEW(ArgType);
// printf("before split name:%s,value:%s\n", arg->name,arg->value);
arg->name = my_alloc_get_str(arg->name, a, 0, spliterPos, 1);
arg->value = my_alloc_get_str(arg->value, a, spliterPos + 1, -1, 1);
printf("after split arg %d name=%s,value=%s\n", i, arg->name, arg->value);
} else { // 无分隔符
arg = NEW(ArgType);
arg->name = my_alloc_cpy_str(arg->name,a);
arg->value = NULL;
}
// 分析好的 ArgType 数据放入链表
if (arg) {
ArgNodeType* newNode = NEW(ArgNodeType);
newNode->arg = arg;
newNode->next = NULL;
if (!firstNode) {
firstNode = newNode;
}
if (curNodeArg) {
curNodeArg->next = newNode;
curNodeArg = newNode;
} else {
curNodeArg = newNode;
}
}
}
if (firstNode) {
ArgType* result = NEW_MULTI(ArgType, argc - 1);
int idx = 0;
ArgNodeType* freeNode;
do
{
freeNode = firstNode;
*(result + idx) = *(firstNode->arg);
firstNode = firstNode->next;
++idx;
free(freeNode);
} while (firstNode);
return result;
}
return NULL;
}
void free_args(const int argc, ArgType* args) {
for (size_t i = 0; i < argc; i++) {
free((*(args + i)).name);
free((*(args + i)).value);
}
free(args);
}
int main(int argc, char* args[]) {
printf("====== normally start test ======\n");
printf("argc == %d\n", argc);
for (size_t i = 0; i < argc; i++) {
printf("arg[%d]=%s\n", i, args[i]);
}
printf("====== args analyzes start test ======\n");
ArgType* result = get_args(argc, args, ':');
if (result) {
printf("args analyzes successfully\n");
for (size_t i = 0; i < argc - 1; i++) {
// printf("%d start\n",i);
printf("==[name=%s,value=%s]==\n",(*(result+i)).name, (*(result+i)).value);
// printf("%d end\n",i);
// ... handle
}
printf("args analyzes & handle complete!\n");
printf("free args start\n");
free_args(argc - 1, result);
printf("free args complete!\n");
} else {
printf("invalidated args, and exit with error code : -1!\n");
return -1;
}
printf("done!\n");
return 0;
}
PS D:\jave\Work Files\C\Studies\24 call app pass args test> gcc .\a.c -o out
PS D:\jave\Work Files\C\Studies\24 call app pass args test> .\out.exe shadow:csm shadowsoft:pcf quality:veryhigh light:on
====== normally start test ======
argc == 5
arg[0]=D:\jave\Work Files\C\Studies\24 call app pass args test\out.exe
arg[1]=shadow:csm
arg[2]=shadowsoft:pcf
arg[3]=quality:veryhigh
arg[4]=light:on
====== args analyzes start test ======
--->split src:shadow:csm,start:0,end:6
start:0,end:6->0:s,1:h,2:a,3:d,4:o,5:w,
endIdx == -1, changed to : 10
--->split src:shadow:csm,start:7,end:10
start:7,end:10->7:c,8:s,9:m,
after split arg 1 name=shadow,value=csm
--->split src:shadowsoft:pcf,start:0,end:10
start:0,end:10->0:s,1:h,2:a,3:d,4:o,5:w,6:s,7:o,8:f,9:t,
endIdx == -1, changed to : 14
--->split src:shadowsoft:pcf,start:11,end:14
start:11,end:14->11:p,12:c,13:f,
after split arg 2 name=shadowsoft,value=pcf
--->split src:quality:veryhigh,start:0,end:7
start:0,end:7->0:q,1:u,2:a,3:l,4:i,5:t,6:y,
endIdx == -1, changed to : 16
--->split src:quality:veryhigh,start:8,end:16
start:8,end:16->8:v,9:e,10:r,11:y,12:h,13:i,14:g,15:h,
after split arg 3 name=quality,value=veryhigh
--->split src:light:on,start:0,end:5
start:0,end:5->0:l,1:i,2:g,3:h,4:t,
endIdx == -1, changed to : 8
--->split src:light:on,start:6,end:8
start:6,end:8->6:o,7:n,
after split arg 4 name=light,value=on
args analyzes successfully
==[name=shadow,value=csm]==
==[name=shadowsoft,value=pcf]==
==[name=quality,value=veryhigh]==
==[name=light,value=on]==
args analyzes & handle complete!
free args start
free args complete!
done!
#include
#include
#include
#define MODE0 0 // 不安全操作模式
#define MODE1 1 // 安全的操作模式
#define MODE2 2 // 可以成功修改的方式正确的方式
#define MODE3 3 // 二级指针方式方式
#define MODE4 4 // 超越长度复制字符串
#define USE_MODE MODE3
void modify_pointer_value(char* pointer, char* value) {
register int i = 0;
while(*(value + i) != '\0') {
*(pointer + i) = *(value + i);
++i;
}
}
void repoint_the_pointer(char* pointer, char* value) {
register int i = 0;
while(*(value + i) != '\0') {
++i;
}
// jave.lin:
// 注意这里再函数里改了pointer参数的指针,相当于换了另一个指针
// 函数执行完后,外部的pointer是不会有任何变化的
// 这个需要了解变量的作用于
pointer = malloc(sizeof(char) * i + 1); // +1因为需要尾部加上'\0'结束符
for (size_t j = 0; j < i; j++) {
*(pointer + j) = *(value + j);
}
*(pointer + i) = '\0';
}
char* repoint_the_pointer2(char* pointer, char* value) {
register int i = 0;
while(*(value + i) != '\0') {
++i;
}
if (!pointer) {
pointer = malloc(sizeof(char) * i + 1); // +1因为需要尾部加上'\0'结束符
}
for (size_t j = 0; j < i; j++) {
*(pointer + j) = *(value + j);
}
*(pointer + i) = '\0';
return pointer;
}
void changedDoublePointer(char** doublePointer, char* value) {
register int i = 0;
while(*(value + i) != '\0') {
++i;
}
char* tempPointer = *(doublePointer);
if (!tempPointer) {
tempPointer = malloc(sizeof(char) * i + 1); // +1因为需要尾部加上'\0'结束符
} else {
tempPointer = realloc(tempPointer, sizeof(char) * i + 1);
}
*(doublePointer) = tempPointer;
for (size_t j = 0; j < i; j++) {
*(tempPointer + j) = *(value + j);
}
*(tempPointer + i) = '\0';
}
int main() {
printf("USE_MODE == %d\n", USE_MODE);
#if USE_MODE == MODE0
char* value = "This is string.";
char* pointer1; // 这时危险的方式,因为pointer1是不确定的地址
printf("before modify pointer1:%s,pointer1'=%p\n",pointer1,pointer1);
modify_pointer_value(pointer1, value);
printf("after modify pointer1:%s,pointer1'=%p\n",pointer1,pointer1);
char* pointer2; // 这时危险的方式,因为pointer1是不确定的地址
printf("before repoint pointer2:%s,pointer2'=%p\n",pointer2,pointer2);
repoint_the_pointer(pointer2, value);
printf("after repoint pointer2:%s,pointer2'=%p\n",pointer2,pointer2);
/*
上面的内容输出:
before modify pointer1:,pointer1'=003B3000
after modify pointer1:This is string.w?h,pointer1'=003B3000
before repoint pointer2:(null),pointer2'=00000000
after repoint pointer2:(null),pointer2'=00000000
done!
可以看到pointer1有乱码,pointer2为NULL
*/
#elif USE_MODE == MODE1
char* value = "This is string.";
// +1因为需要处理补上'\0',因为strlen不計算'\0'结束符
// 这样指向地址之后,就不会有危险操作了
// malloc 不会初始化 分配的内容,所以有可能before modify之前会看到乱码的输出
// 如果需要 初始化 分配的内容,可以使用calloc,但是没必要,反正modify_pointer_value都要更改指针内容
char* pointer1 = malloc(strlen(value) + 1);
printf("before modify pointer1:%s,pointer1'=%p\n",pointer1,pointer1);
modify_pointer_value(pointer1, value);
printf("after modify pointer1:%s,pointer1'=%p\n",pointer1,pointer1);
// 因为repointer会重新分配这里就没有必要去alloc
// 但是从输出结果来看,pointer2在执行完repoint_the_pointer后
// pointer2的内容还是NULL
char* pointer2 = NULL;
printf("before repoint pointer2:%s,pointer2'=%p\n",pointer2,pointer2);
repoint_the_pointer(pointer2, value);
printf("after repoint pointer2:%s,pointer2'=%p\n",pointer2,pointer2);
/*
上面的内容输出:
before modify pointer1:?f,pointer1'=00661598
after modify pointer1:This is string.,pointer1'=00661598
before repoint pointer2:(null),pointer2'=00000000
after repoint pointer2:(null),pointer2'=00000000
done!
从结果上来看,pointer2还是NULL的,我们还是需要另一中方法来处理
*/
#elif USE_MODE == MODE2
char* value = "This is string.";
// +1因为需要处理补上'\0',因为strlen不計算'\0'结束符
// 这样指向地址之后,就不会有危险操作了
// malloc 不会初始化 分配的内容,所以有可能before modify之前会看到乱码的输出
// 如果需要 初始化 分配的内容,可以使用calloc,但是没必要,反正modify_pointer_value都要更改指针内容
char* pointer1 = malloc(strlen(value) + 1);
printf("before modify pointer1:%s,pointer1'=%p\n",pointer1,pointer1);
modify_pointer_value(pointer1, value);
printf("after modify pointer1:%s,pointer1'=%p\n",pointer1,pointer1);
// 注意MODE2模式中,我们使用的是 repoint_the_pointer2 函数(结尾有个2)
char*pointer2 = NULL;
printf("before repoint pointer2:%s,pointer2'=%p,sizeof(pointer2)=%d\n",pointer2,pointer2,sizeof(pointer2));
// 解决方式很简单,我们对原来的
pointer2 = repoint_the_pointer2(pointer2, value);
printf("after repoint pointer2:%s,pointer2'=%p,sizeof(pointer2)=%d\n",pointer2,pointer2,sizeof(pointer2));
/*
上面的内容输出:
before modify pointer1:?f,pointer1'=00661598
after modify pointer1:This is string.,pointer1'=00661598
before repoint pointer2:(null),pointer2'=00000000
after repoint pointer2:(null),pointer2'=00000000
done!
从结果上来看,pointer2还是NULL的,我们还是需要另一中方法来处理
*/
#elif USE_MODE == MODE3
// 再来看看二级指针的方式
char* pointer3 = malloc(sizeof(char) * 1);
printf("before changedDoublePointer pointer3=%s,pointer3=%p\n", pointer3,pointer3);
changedDoublePointer(&pointer3, "hello world!");
printf("after changedDoublePointer pointer3=%s,pointer3=%p\n", pointer3,pointer3);
/*
USE_MODE == 3
before changedDoublePointer pointer3=??pointer3=00C61598
after changedDoublePointer pointer3=hello world!,pointer3=00C61598
done!
*/
#elif USE_MODE == MODE4
// 危险操作!!
// 注意我们分配给 pointer4 的只有1个字节长度的空间
char* pointer4 = malloc(sizeof(char) * 1);
printf("before copy pointer4=%s\n", pointer4);
// 但是我们用了一个hello 5个字节空间的复制到 pointer4 ,那么对 pointer4 的越界操作也是危险的
strcpy(pointer4, "hello");
printf("after copy pointer4=%s\n", pointer4); // pointer4 == "hello",除了第一个h字符是安全的操作,后面的都是不安全的
/*
USE_MODE == 4
before copy pointer4=??
after copy pointer4=hello
done!
*/
#endif
printf("done!\n");
return 0;
}
#define DATE_TYPE1 1
#define DATE_TYPE2 2
#define DATE_TYPE3 3
#define DATE_TYPE4 4
#define DATE_TYPE5 5
#define DATE_TYPE6 6
#define DATE_TYPE7 7
#define DATA_TYPE 7
#if DATA_TYPE == DATE_TYPE1
#define ElementType char
#define FORMAT "%d,"
#elif DATA_TYPE == DATE_TYPE2
#define ElementType short
#define FORMAT "%d,"
#elif DATA_TYPE == DATE_TYPE3
#define ElementType unsigned
#define FORMAT "%d,"
#elif DATA_TYPE == DATE_TYPE4
#define ElementType int
#define FORMAT "%d,"
#elif DATA_TYPE == DATE_TYPE5
#define ElementType float
#define FORMAT "%f,"
#elif DATA_TYPE == DATE_TYPE6
#define ElementType double
#define FORMAT "%lf,"
#elif DATA_TYPE == DATE_TYPE7
#define ElementType long double
#define FORMAT "%LG,"
// 为了输出long double
// long double 怎样输出?
// https://www.zhihu.com/question/64387466
#define __USE_MINGW_ANSI_STDIO 1
#else
#define ElementType long long
#define FORMAT "%ld,"
#endif
#include
#include
int main() {
printf("======================\n");
printf("double pointer test start\n");
// 二级指针
const int w = 4;
const int h = 3;
const int e_size = sizeof(ElementType);
const int mem_size = e_size * (w * h);
printf("w:%d, h:%d, element size:%d(0x%X), format:%s\n", w, h, e_size, e_size, FORMAT);
ElementType _2d_arr[3][4] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12
};
// 测试指向一级指针
ElementType* p = (void*)&_2d_arr;
// 指向二级指针
ElementType** q = &p;
// 从下面的q2,q3测试可得
// 每多一级指针,都是间隔了一级地址(地址数据需要一个int,所以都会间隔4 bytes)
ElementType*** q2 = &q;
// 计算出每一行需要的字节数
int rowSize = sizeof(_2d_arr[0]);
int rowStep = rowSize / e_size;
printf("row size:%d(0x%X)\n",rowSize,rowSize);
printf("p:%p\n", p);
printf("q:%p\n", q);
printf("q+1:%p\n", q+1);
printf("q2:%p\n", q2);
printf("q2+1:%p\n", q2+1);
printf("q2+2:%p\n", q2+2);
printf("&_2d_arr:%p\n", &_2d_arr);
printf("&_2d_arr[0]:%p\n", &_2d_arr[0]);
printf("&_2d_arr[1]:%p\n", &_2d_arr[1]);
printf("&_2d_arr[2]:%p\n", &_2d_arr[2]);
// 通过二级指针来遍历
for (size_t i = 0; i < h; i++) {
ElementType* row = (*q) + (i * rowStep);
printf("row[%d]:%p\n", i, row);
printf("row:%d:", i);
for (size_t j = 0; j < w; j++) {
printf(FORMAT, (ElementType)*(row + j));
}
printf("\n");
}
printf("double pointer test end\n");
printf("======================\n");
return 0;
}
运行会有警告使用了 过期宏定义:__USE_MINGW_ANSI_STDIO
PS D:\jave\Work Files\C\Studies\8 multi D array test> gcc .\b.c -o out In file included from c:\mingw\include\stdio.h:55,
from .\b.c:41:
c:\mingw\include\_mingw.h:413:3: warning: #warning "Direct definition of __USE_MINGW_ANSI_STDIO is deprecated." [-Wcpp]
413 | # warning "Direct definition of __USE_MINGW_ANSI_STDIO is deprecated."
| ^~~~~~~
c:\mingw\include\_mingw.h:414:10: note: #pragma message: See <_mingw.h> for preferred feature activation methods.
414 | # pragma message "See <_mingw.h> for preferred feature activation methods."
| ^~~~~~~
PS D:\jave\Work Files\C\Studies\8 multi D array test> .\out.exe ======================
double pointer test start
w:4, h:3, element size:12(0xC), format:%LG,
row size:48(0x30)
p:0062fe58
q:0062fe54
q+1:0062fe58
q2:0062fe50
q2+1:0062fe54
q2+2:0062fe58
&_2d_arr:0062fe58
&_2d_arr[0]:0062fe58
&_2d_arr[1]:0062fe88
&_2d_arr[2]:0062feb8
row[0]:0062fe58
row:0:1,2,3,4,
row[1]:0062fe88
row:1:5,6,7,8,
row[2]:0062feb8
row:2:9,10,11,12,
double pointer test end
======================
#include
#include
#include
int main() {
float d = 0;
float n = 1;
assert(d != 0);
float v = d / n;
printf("d/n=v\n");
printf("%f/%f=%f\n", d, n, v);
printf("done!\n");
return 0;
}
/*
assert(true) 则通过
assert(false) 则抛出异常
运行输出
Assertion failed: d != 0, file .\a.c, line 10
*/
浮点数是如何构成的: float value = mantissa * (2 ^ exponent);
// https://www.runoob.com/cprogramming/c-standard-library-assert-h.html
// https://www.runoob.com/cprogramming/c-macro-assert.html
// 下一个测试math
// double frexp(double x, int *exponent)
// 把浮点数 x 分解成尾数和指数。返回值是尾数,并将指数存入 exponent 中。所得的值是 x = mantissa * 2 ^ exponent。
#include
#include
int main() {
double v = 99.123;
double mantissa = 0;
int exponent = 0;
mantissa = frexp(v, &exponent);
printf("frexp(%lf), mantissa=%lf, exponent=%d\n", v, mantissa, exponent);
double v1 = mantissa * (pow((double)2, (double)exponent));
printf("v1 = mantissa * 2 ^ exponent\n");
printf("v1 = %lf * (2 ^ %d)\n", mantissa, exponent);
printf("v1 = %lf\n",v1);
double v2 = ldexp(mantissa, exponent);
printf("v2 = %lf\n", v2);
return 0;
}
frexp(99.123000), mantissa=0.774398, exponent=7
v1 = mantissa * 2 ^ exponent
v1 = 0.774398 * (2 ^ 7)
v1 = 99.123000
v2 = 99.123000
以下参考了:frexp ( )【C语言库函数源代码】
【C语言库函数源代码】
【本程序在Dev C++ 4.9.9.2 下编译通过】
/*
把浮点数x分解成尾数和指数。x=m*2^exptr,m为规格化小数。
返回尾数m,并将指数存入exptr中。
*/
double my_frexp01(double x, int *exptr)
{
union
{
double d;
unsigned char c[8];
} u;
u.d = x;
//得到移码,并减去1022得到指数值。
*exptr = (int)(((u.c[7] & 0x7f) << 4) | (u.c[6] >> 4)) - 1022;
//把指数部分置为0x03FE
u.c[7] &= 0x80;
u.c[7] |= 0x3f;
u.c[6] &= 0x0f;
u.c[6] |= 0xe0;
return u.d;
}
double my_frexp02(double x, int *eptr)
{
union
{
double v;
struct
{
unsigned mantissa2 : 32;
unsigned mantissa1 : 20;
unsigned exponent : 11;
unsigned sign : 1;
} s;
} u;
if (x)
{
u.v = x;
//得到移码,并减去1022得到指数值。
*eptr = u.s.exponent - 1022;
//把指数部分置为0x03FE
u.s.exponent = 1022;
return(u.v);
}
else
{
*eptr = 0;
return((double)0);
}
}
main()
{
float x,y;
int exp;
y = 64.0;
x = my_frexp01(y,&exp);
printf("%f=%.2f*2^%d/n",y,x,exp);
x = my_frexp01(-y,&exp);
printf("%f=%.2f*2^%d/n",y,x,exp);
printf("/n************************/n");
x = my_frexp02(y,&exp);
printf("%f=%.2f*2^%d/n",y,x,exp);
x = my_frexp02(-y,&exp);
printf("%f=%.2f*2^%d/n",y,x,exp);
system("pause");
return 0;
}
在#include
之前添加:#define __USE_MINGW_ANSI_STDIO 1
// 为了输出long double
// long double 怎样输出?
// https://www.zhihu.com/question/64387466
#define __USE_MINGW_ANSI_STDIO 1
format字符串使用"%LG"
long double a = 999.99;
printf("a = %LG\n", a); // output : a = 999.99
// jave.lin testing the signal
#include
#include
#include
// #define SIGTERM 15 // Software termination signal from kill
// 用一个内置的ID,因为自定义的安装不了信号处理
// #define CUSTOM_SIGNAL 1 // 无效
#define CUSTOM_SIGNAL 15
#define SETUP_SIGNAL(SIG,handler)\
{\
void(*cb)(int) = signal(SIG, handler);\
if (cb == SIG_ERR) printf("setup " #SIG " error,%d\n", (int)cb); \
else printf("setup " #SIG " signal, return : %d\n", (int)cb);\
}\
// 信号处理回调
void signalHandler(int);
// 中断循环周期
char breakSignal = 0;
// 但循环睡眠时长:毫秒
int sleepMS = 1000;
// 触发自定义事件统计变量
int triggerCounter = 0;
// 触发自定义事件超过指定次数则退出程序
#define TRIGGER_MAX 2
void (*signalCallback)(int);
int main() {
/*
signal.h中的定义
typedef void (__CRTDECL* _crt_signal_t)(int);
#define NSIG 23 // maximum signal number + 1
// Signal types
#define SIGINT 2 // interrupt
#define SIGILL 4 // illegal instruction - invalid function image
#define SIGFPE 8 // floating point exception
#define SIGSEGV 11 // segment violation
#define SIGTERM 15 // Software termination signal from kill
#define SIGBREAK 21 // Ctrl-Break sequence
#define SIGABRT 22 // abnormal termination triggered by abort call
#define SIGABRT_COMPAT 6 // SIGABRT compatible with other platforms, same as SIGABRT
// Signal action codes
#define SIG_DFL ((_crt_signal_t)0) // default signal action
#define SIG_IGN ((_crt_signal_t)1) // ignore signal
#define SIG_GET ((_crt_signal_t)2) // return current value
#define SIG_SGE ((_crt_signal_t)3) // signal gets error
#define SIG_ACK ((_crt_signal_t)4) // acknowledge
#ifdef _CORECRT_BUILD
// Internal use only! Not valid as an argument to signal().
#define SIG_DIE ((_crt_signal_t)5) // terminate process
#endif
// Signal error value (returned by signal call on error)
#define SIG_ERR ((_crt_signal_t)-1) // signal error value
*/
// step signal handler
SETUP_SIGNAL(SIGINT,signalHandler)
SETUP_SIGNAL(SIGFPE,signalHandler)
SETUP_SIGNAL(SIGBREAK,signalHandler)
SETUP_SIGNAL(CUSTOM_SIGNAL,signalHandler)
printf("one.\n");
printf("Sleep(1000);\n");
// stdlib.h下的sleep(s),unit:seconds,过期函数
// Windows.h下的Sleep(ms); ms:毫秒
Sleep(1000);
float fv = 9999999999999999900000000099999999.99999999999;
printf("fv=%f.\n", fv); // 这么大都不溢出,有点奇怪,可能编译器截断了
// let floating point exception
raise(SIGFPE); // 手动触发信号
printf("two.\n");
printf("start loop\n");
int counter = 0;
while(!breakSignal) {
printf("tick! & sleep(%d)\n", sleepMS);
Sleep(sleepMS);
if (++counter > 4) {
counter = 0;
printf("tick per 5 times raise custom signal\n", sleepMS);
raise(CUSTOM_SIGNAL); // 手动触发信号
}
}
printf("break loop done!\n");
return 0;
}
// 信号处理
void signalHandler(int signalCode) {
switch (signalCode) {
case SIGINT:
printf("receive ctrl+c interupt signal to exit.\n");
exit(0);
break;
case SIGFPE:
printf("receive floating point exception.\n");
break;
case SIGBREAK:
printf("receive ctrl + Break/Pause signal to exit.\n");
breakSignal = 1;
break;
case CUSTOM_SIGNAL:
printf("receive custom signal.\n");
if (sleepMS == 1000) {
printf("setting sleep ms to : 100\n");
sleepMS = 100;
} else {
printf("setting sleep ms to : 1000\n");
sleepMS = 1000;
}
if (++triggerCounter > TRIGGER_MAX) {
printf("trigger times researched, so safely exit.\n");
exit(0);
}
// setup again
SETUP_SIGNAL(CUSTOM_SIGNAL,signalHandler)
break;
default:
printf("un handle signal code : %d", signalCode);
break;
}
}
下面是自然结束的输出:
也可以手动ctrl+c,或是ctrl+break/pause都可以结束
setup SIGINT signal, return : 0
setup SIGFPE signal, return : 0
setup SIGBREAK signal, return : 0
setup CUSTOM_SIGNAL signal, return : 0
one.
Sleep(1000);
fv=9999999790214768000000000000000000.000000.
receive floating point exception.
two.
start loop
tick! & sleep(1000)
tick! & sleep(1000)
tick! & sleep(1000)
tick! & sleep(1000)
tick! & sleep(1000)
tick per 5 times raise custom signal
receive custom signal.
setting sleep ms to : 100
setup CUSTOM_SIGNAL signal, return : 0
tick! & sleep(100)
tick! & sleep(100)
tick! & sleep(100)
tick! & sleep(100)
tick! & sleep(100)
tick per 5 times raise custom signal
receive custom signal.
setting sleep ms to : 1000
setup CUSTOM_SIGNAL signal, return : 0
tick! & sleep(1000)
tick! & sleep(1000)
tick! & sleep(1000)
tick! & sleep(1000)
tick! & sleep(1000)
tick per 5 times raise custom signal
receive custom signal.
setting sleep ms to : 100
trigger times researched, so safely exit.
可以去查看文档或是看看stdlib.h
中的API,还有N中转换数据接口
/*
C语言中将字符串转换为数字的方法
https://blog.csdn.net/weixin_34364071/article/details/86054032
atof() 将字符串转换为双精度浮点型值
atoi() 将字符串转换为整型值
atol() 将字符串转换为长整型值
strtod() 将字符串转换为双精度浮点型值,并报告不能被转换的所有剩余数字
strtol() 将字符串转换为长整值,并报告不能被转换的所有剩余数字
strtoul() 将字符串转换为无符号长整型值,并报告不能被转换的所有剩余数字4
*/
// 为了long double能正常输出
#define __USE_MINGW_ANSI_STDIO 1
#include
#include
#include
int main() {
char* char_str = "100";
char* short_str = "32765";
char* unsigned_str = "65535";
char* int_str = "20000";
char* float_str = "3.14";
char* double_str = "3.14159265359";
char* longlong_str = "22345678987654322";
char* longlong64_str = "32345678987654323";
char* longdouble_str = "9876543214567890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.1234567898765432100000000000";
char* longdouble_str_convert_left;
char* long_str_convert_left;
char char_v = (char)atoi(char_str); // 没有char的
short short_v = (short)atoi(short_str); // 也没有short的
unsigned unsigned_v = atoi(unsigned_str);
int int_v = atoi(unsigned_str);
float float_v = (float)atof(float_str); // 没有float的
double double_v = atof(double_str);
long long longlong_v = atoll(longlong_str);
__int64 longlong64_v = _atoi64(longlong64_str);
long double longdouble_v = strtold(longdouble_str, &longdouble_str_convert_left);
long long long_v2 = strtoul(longdouble_str, &long_str_convert_left, 10);
printf("start\n");
printf("char_v:%c\n", char_v);
printf("short_v:%d\n", short_v);
printf("unsigned_v:%d\n", unsigned_v);
printf("int_v:%d\n", int_v);
printf("float_v:%f\n", float_v);
printf("double_v:%f\n", double_v);
printf("longlong_v:%lld\n", longlong_v);
printf("longlong64_v:%lld\n", longlong64_v);
printf("longdouble_v:%LG, left_str:%s\n", longdouble_v, longdouble_str_convert_left);
printf("long_v2:%lld, left_str:%s\n", long_v2, long_str_convert_left);
printf("end\n");
/*
start
char_v:d
short_v:32765
unsigned_v:65535
int_v:65535
float_v:3.140000
double_v:3.141593
longlong_v:22345678987654322
longlong64_v:32345678987654323
longdouble_v:9.87654E+1341, left_str:
long_v2:4294967295, left_str:.1234567898765432100000000000
end
从上面的输出结果来看,对于long double 的输出真的是服气
都1K+的10的次方了,还没有溢出剩余的部分,有点可怕的长度
而long_v2就溢出了可以看到left_str部分,而且还不全
*/
return 0;
}
#include
#include
// jave.lin : 下面是 offsetof 的宏定义,他是以NULL为起始地址来取对象的地址值来计算偏移的
// #define offsetof(s,m) ((size_t)&(((s*)0)->m))
typedef struct Info {
// 下面c~c3会在一个4 bytes,以最大成员的int的宽度对齐
char c; // 1 byte
char c1; // 1 byte
char c2; // 1 byte
char c3; // 1 byte
int a; // 4 bytes
char* str; // 8 bytes = int 4 bytes for string pointer + int 4 bytes for second level pionter
int b; // 4 bytes
char arr[10]; // 10 bytes
} InfoType;
int main() {
#define PRINT_OFFSET(Type,Mem)\
printf("Member:'"#Mem "' in Type:'" #Type "' offset is : %d\n", offsetof(Type, Mem));
printf("start\n");
printf("sizeof(InfoType) : %d\n", sizeof(InfoType));
PRINT_OFFSET(InfoType, c);
PRINT_OFFSET(InfoType, a);
PRINT_OFFSET(InfoType, str);
PRINT_OFFSET(InfoType, b);
PRINT_OFFSET(InfoType, arr);
printf("end\n");
return 0;
}
start
sizeof(InfoType) : 28
Member:'c' in Type:'InfoType' offset is : 0
Member:'a' in Type:'InfoType' offset is : 4
Member:'str' in Type:'InfoType' offset is : 8
Member:'b' in Type:'InfoType' offset is : 12
Member:'arr' in Type:'InfoType' offset is : 16
end
#include
#include
// atexit 需要 stdlib.h
void beforeNormallyExitAppHandler() {
printf("==before nromally exit the application handler here.==\n");
}
int main() {
printf("before setup atexit callback.\n");
atexit(beforeNormallyExitAppHandler);
printf("after setup atexit callback.\n");
printf("before exitting.\n");
return 0;
}
before setup atexit callback.
after setup atexit callback.
before exitting.
==before nromally exit the application handler here.==
#include
#include
// getenv 需要stdlib
// char *getenv(const char *name)
int main() {
#define PRINT_ENV_VAR(name)\
printf("[" #name "] : %s\n\n", getenv("" #name));
PRINT_ENV_VAR(PATH)
PRINT_ENV_VAR(JAVA_HOME)
PRINT_ENV_VAR(CLASS_PATH)
return 0;
}
[PATH] : C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\iCLS\;C:\Program Files\Intel\Intel(R) Management Engine Components\iCLS\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;"D:\Program Files\Java\jdk1.8.0_211\bin;D:\Program Files\Java\jdk1.8.0_211\jre\bin;";C:\MinGW\bin;C:\Users\jave\AppData\Local\Microsoft\WindowsApps;;C:\Users\jave\AppData\Local\Programs\Microsoft VS Code\bin
[JAVA_HOME] : D:\Program Files\Java\jdk1.8.0_211
[CLASS_PATH] : D:\Program Files\Java\jdk1.8.0_211\lib
#include
#include
// system 需要 stdlib.h
int main() {
printf("list the current directory file infos.\n");
// system("ls"); // gci/ls/dir 都可以, -r是递归目录
// system("ls -r"); // gci/ls/dir 都可以, -r是递归目录
// system("gci"); // gci/ls/dir 都可以, -r是递归目录
// system("gci -r"); // gci/ls/dir 都可以, -r是递归目录
system("dir"); // gci/ls/dir 都可以, -r是递归目录
// system("dir -r"); // gci/ls/dir 都可以, -r是递归目录
// 上面的测试发现在windows中,带了参数的这样调用是不行的,是有无参数的dir是可以执行的。
// 直接在power shell或是cmd下,上面的所有指令都是可行的
printf("press any key to exit.\n");
// pause
system("pause");
return 0;
}
list the current directory file infos.
驱动器 D 中的卷没有标签。
卷的序列号是 FAB7-6D0B
D:\jave\Work Files\C\Studies\33 system test 的目录
2020/04/21 16:02 <DIR> .
2020/04/21 16:02 <DIR> ..
2020/04/21 16:02 846 a.c
2020/04/21 15:52 <DIR> dir1
2020/04/21 15:52 <DIR> dir2
2020/04/21 16:02 43,265 out.exe
2 个文件 44,111 字节
4 个目录 902,984,269,824 可用字节
press any key to exit.
请按任意键继续. . .
PS D:\jave\Work Files\C\Studies\33 system test> dir -r
目录: D:\jave\Work Files\C\Studies\33 system test
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/4/21 15:52 dir1
d----- 2020/4/21 15:52 dir2
-a---- 2020/4/21 16:02 846 a.c
-a---- 2020/4/21 16:02 43265 out.exe
目录: D:\jave\Work Files\C\Studies\33 system test\dir1
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2020/4/21 15:52 0 test1.txt
-a---- 2020/4/21 15:52 0 test2.txt
目录: D:\jave\Work Files\C\Studies\33 system test\dir2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2020/4/21 15:52 0 albedo.bmp
-a---- 2020/4/21 15:52 0 ao.bmp
-a---- 2020/4/21 15:52 0 height.bmp
-a---- 2020/4/21 15:52 0 normal.bmp
-a---- 2020/4/21 15:52 0 specular.bmp
先查看size工具帮助
一下说明是该工具可以显示二进制内部的块大小,如果没设置输入文件,将以a.out为默认的输入
PS D:\jave\Work Files\C\Studies\36 size test> size -h Usage: C:\MinGW\bin\size.exe [option(s)] [file(s)]
Displays the sizes of sections inside binary files
If no input file(s) are specified, a.out is assumed
The options are:
-A|-B --format={sysv|berkeley} Select output style (default is berkeley)
-o|-d|-x --radix={8|10|16} Display numbers in octal, decimal or hex
-t --totals Display the total sizes (Berkeley only)
--common Display total size for *COM* syms
--target=<bfdname> Set the binary file format
@<file> Read options from <file>
-h --help Display this information
-v --version Display the program's version
C:\MinGW\bin\size.exe: supported targets: pe-i386 pei-i386 elf32-i386 elf32-iamcu elf32-little elf32-big plugin srec symbolsrec verilog tekhex binary ihex
下面是使用
PS D:\jave\Work Files\C\Studies\36 size test> size .\out.exe -B -d -t text data bss dec hex filename
15456 1528 112 17096 42c8 .\out.exe
15456 1528 112 17096 42c8 (TOTALS)
PS D:\jave\Work Files\C\Studies\36 size test> size .\out.exe -A -d -t .\out.exe :
section size addr
.text 11460 4198400
.data 24 4210688
.rdata 1572 4214784
.eh_frame 2424 4218880
.bss 112 4222976
.idata 1448 4227072
.CRT 24 4231168
.tls 32 4235264
.debug_aranges 56 4239360
.debug_info 7884 4243456
.debug_abbrev 329 4251648
.debug_line 452 4255744
.debug_frame 56 4259840
.debug_str 134 4263936
Total 26007
// jave.lin 这个例子我们只演示同一个方法内的jmp处理
#include
#include
#include
// setjmp longjmp test
static jmp_buf stack_frame_buff;
int main() {
int a = 1;
int b = 2;
int counter = 0;
const int max = 5;
char th_str[4][10] = { "%dst", "%dnd", "%dthd", "%dth" };
char th_str_v[10];
int idx = 0;
printf("before setjmp, a=%d, b=%d, stack_frame_buff=%p\n", a, b, stack_frame_buff);
int ret = setjmp(stack_frame_buff); // jave.lin:第一次 Label 的地方
if (ret == 0) {
printf("=====this is directly call setjmp, return 0.\n");
} else {
printf("=====this is longjmp(buff, 1) call, return %d\n", ret);
}
ret = setjmp(stack_frame_buff); // jave.lin:第二次 Label 会将前一次的 覆盖掉,当longjmp同一个stack_frame_buff时,只会跳转到最后一个setjmp的地方
if (ret == 0) {
printf("-----this is directly call setjmp, return 0.\n");
} else {
printf("-----this is longjmp(buff, 1) call, return %d\n", ret);
}
printf("after setjmp, a=%d, b=%d, stack_frame_buff=%p\n", a, b, stack_frame_buff);
b = 1;
a = 2;
printf("after modify, a=%d, b=%d\n", a, b);
printf("Sleep(1000)\n");
Sleep(1000);
printf("now longjmp(stack_frame_buff, 1)\n");
if (counter++ < max) {
idx = counter - 1;
idx = idx > 3 ? 3 : idx;
sprintf(th_str_v, th_str[idx], counter);
printf("longjmp %s times reaching.\n", th_str_v);
longjmp(stack_frame_buff, 1); // jave.lin:只跳转到该stack_frame_buff记录的栈帧数据的最后一帧,意思如果重复set的话,只会jmp到最后一次set的stack_frame_buff的帧数据
} else {
printf("longjmp %d times reaching.\n", max);
}
printf("done!\n");
return 0;
}
before setjmp, a=1, b=2, stack_frame_buff=00407020
=====this is directly call setjmp, return 0.
-----this is directly call setjmp, return 0.
after setjmp, a=1, b=2, stack_frame_buff=00407020
after modify, a=2, b=1
Sleep(1000)
now longjmp(stack_frame_buff, 1)
longjmp 1st times reaching.
-----this is longjmp(buff, 1) call, return 1
after setjmp, a=2, b=1, stack_frame_buff=00407020
after modify, a=2, b=1
Sleep(1000)
now longjmp(stack_frame_buff, 1)
longjmp 2nd times reaching.
-----this is longjmp(buff, 1) call, return 1
after setjmp, a=2, b=1, stack_frame_buff=00407020
after modify, a=2, b=1
Sleep(1000)
now longjmp(stack_frame_buff, 1)
longjmp 3thd times reaching.
-----this is longjmp(buff, 1) call, return 1
after setjmp, a=2, b=1, stack_frame_buff=00407020
after modify, a=2, b=1
Sleep(1000)
now longjmp(stack_frame_buff, 1)
longjmp 4th times reaching.
-----this is longjmp(buff, 1) call, return 1
after setjmp, a=2, b=1, stack_frame_buff=00407020
after modify, a=2, b=1
Sleep(1000)
now longjmp(stack_frame_buff, 1)
longjmp 5th times reaching.
-----this is longjmp(buff, 1) call, return 1
after setjmp, a=2, b=1, stack_frame_buff=00407020
after modify, a=2, b=1
Sleep(1000)
now longjmp(stack_frame_buff, 1)
longjmp 5 times reaching.
done!
#include
#include
#include
static int get_result_buff_jmp_counter = 0;
static jmp_buf get_result_buff;
void GetResult(int* result) {
if (get_result_buff_jmp_counter != 0) {
longjmp(get_result_buff, get_result_buff_jmp_counter++);
}
// 不要放这里,因为不会恢复栈帧数据
// int num = 1000;
int ret = setjmp(get_result_buff);
int num = 1000;
if (ret == 0) {
get_result_buff_jmp_counter = 1;
}
if (ret < 3 ) {
*result = num + ret;
} else {
*result = -1;
get_result_buff_jmp_counter = 0;
}
}
int main() {
printf("GetResult start\n");
int result;
do
{
GetResult(&result);
if (result != -1) {
printf("Get result : %d\n", result);
} else {
break;
}
} while (1);
printf("GetResult end\n");
return 0;
}
GetResult start
Get result : 1000
Get result : 1001
Get result : 1002
GetResult end
#include
#include
#include
static jmp_buf buff;
void b_func(int* num) {
printf("enter b_func. and jmp back to main func.\n");
(*num)++;
longjmp(buff, 1);
}
int main() {
int main_a = 999;
char main_b[10] = "test";
int main_c = 1;
printf("before setjmp main_a=%d, main_b=%s, main_c=%d\n", main_a, main_b, main_c);
if (setjmp(buff) == 0) {
strcpy(main_b, "hello");
printf("first setjmp, to run b_func. main_a=%d, main_b=%s, main_c=%d\n", ++main_a, main_b, ++main_c);
// 注意这里我们在 b_func 修改了main_c
// 但是跳转回来后 main_c 的值还是 b_func 修改后的值
b_func(&main_c);
} else {
// 注意这里我们在 b_func 修改了main_c
// 但是跳转回来后 main_c 的值还是 b_func 修改后的值,并没有恢复到 setjmp 时候的栈帧数据
printf("jmp back from b_func. main_a=%d, main_b=%s, main_c=%d\n", main_a, main_b, main_c);
}
printf("done!\n");
return 0;
}
before setjmp main_a=999, main_b=test, main_c=1
first setjmp, to run b_func. main_a=1000, main_b=hello, main_c=2
enter b_func. and jmp back to main func.
jmp back from b_func. main_a=1000, main_b=hello, main_c=3
done!
#include
typedef struct Person {
char* name;
unsigned char age;
} Person;
int main() {
Person p = { "Name", 18 }; // 无字段名,则需要按字段顺序初始化
printf("p.name:%s, p.age:%d\n", p.name, p.age);
Person p1 = { .age = 20, .name = "tony" }; // 有字段名,可以不按字段顺序初始化
printf("p1.name:%s, p1.age:%d\n", p1.name, p1.age);
return 0;
}