2022-02-26

WARNING: This article may be obsolete
This post was published in 2022-02-26. Obviously, expired content is less useful to users if it has already pasted its expiration date.
This article is categorized as "Garbage" . It should NEVER be appeared in your search engine's results.


Futures and promises

英文wikipedia: 🔗 [Futures and promises - Wikipedia] https://en.wikipedia.org/wiki/Futures_and_promises

中文wikipedia: 🔗 [Future与promise - 维基百科,自由的百科全书] https://zh.wikipedia.org/zh-hans/Future与promise

strcmp

 strcmp  🔗 [strcmp - C++ Reference] https://www.cplusplus.com/reference/cstring/strcmp/

C语言数组的入门内容

作为本笔记后半部分的前置入门笔记,于2023-02-13补充。

命名一个未初始化的数组,使用 sizeof(arr) / sizeof(arr[0]) 获取它的长度,然后打印数组内容---脏数值

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[5];
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
        printf("%d, ", arr[i]);
        // 0, 0, 4198464, 0, -925041520, 
    }
    return 0;
}

使用malloc()创建一个长度为10的数组( 注意:使用malloc以后就不能通过sizeof()的方法捞出数组长度了,只能一开始就记住 , ref),然后打印数组内容(大多数时候我们会得到一堆0, 但这并不是malloc()的行为 ,而是操作系统的行为,见:🔗 [c - Why does malloc initialize the values to 0 in gcc? - Stack Overflow] https://stackoverflow.com/questions/8029584/why-does-malloc-initialize-the-values-to-0-in-gcc). 使用calloc()则会让分配的数组空间全部初始化为0,具体可以参考之前的笔记:🔗 2022-01-23

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char const *argv[]) {
    int *arr = (int *) calloc(10, sizeof(int));
    //  int *arr = (int *) malloc(10 * sizeof(int));
    for (int i = 0; i < 10; i++) {
        printf("%d, ", arr[i]);
        // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    }
    return 0;
}

创建一个带有初始化数值的数组,打印一些基本信息(长度、内容等):

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[] = {1, 2, 3, 4, 5};

    printf("sizeof arr: %d\n", sizeof(arr));
    // sizeof arr: 20
    printf("sizeof(arr) / sizeof(arr[0]): %d\n", sizeof(arr) / sizeof(arr[0]));
    // sizeof(arr) / sizeof(arr[0]): 5
    return 0;
}
#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[] = {1, 2, 3, 4, 5};
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
        printf("%d, ", arr[i]);
        // 1, 2, 3, 4, 5,
    }
    return 0;
}

数组通过参数传递与返回

总而言之就是:在目前学到过的C语言知识里,C语言传递数组的能力很薄弱,任何和数组沾边的传递都是靠指针来运作的。所以有的时候我们发现仅仅传递一个指针还不够,有的时候我们需要传递一个结构体,把长度等额外信息一起捞过去。

C语言并没有int[] helper()这样的写法。🔗 [Returning an array using C - Stack Overflow] https://stackoverflow.com/questions/11656532/returning-an-array-using-c

void helper(int *arr)
// 传递数组的头指针

void helper(int arr[])
// 还是传递数组的头指针,和上面那个方法本质上是一样的

int* arr_creater(int size)
// 返回数组的头指针,但不包含数组的长度,所以这种写法需要我们事先知道创建数组的长度


struct dynamic_arr {
    int *start;
    int size;
};
struct dynamic_arr *create_arr()
// 返回一个结构体,包含数组的头指针和数组的长度

通过参数传递数组时,能够成功传递过去的信息 只有 指向arr[0]的指针。由于 sizeof() 是compile time operator,我们永远无法在传递参数以后获取数组的长度,只能把数组长度作为一个额外参数一起传递过去。(这一点看起来很合理,但有的时候又不合理,凭什么 free() 就不需要我们提供释放空间的大小?见:🔗 [free()函数如何知道要释放的空间大小? - 知乎] https://www.zhihu.com/question/302440083

下面这个程序无法在helper()方法里获取数组长度:

#include<stdio.h>

void helper(int arr[]) {
    printf("helper() sizeof arr: %lu\n", sizeof(arr));
    // helper() sizeof arr: 8
}

int main(int argc, char const *argv[]) {
    int arr[] = {1, 2, 3, 4, 5};
    printf("main() sizeof arr: %lu\n", sizeof(arr));
    // main() sizeof arr: 20
    helper(arr);
    return 0;
}

下面这个程序把数组长度 arr_size 当作参数一起传过去了:

#include<stdio.h>

void helper(int arr[], int arr_size) {
    printf("helper() sizeof arr: %lu\n", sizeof(arr));
    // helper() sizeof arr: 8
    printf("real size: %d\n", arr_size);
    // real size: 5

}

int main(int argc, char const *argv[]) {
    int arr[] = {1, 2, 3, 4, 5};
    printf("main() sizeof arr: %lu\n", sizeof(arr));
    // main() sizeof arr: 20
    helper(arr, sizeof(arr) / sizeof(arr[0]));
    return 0;
}

一个小程序练习:创建一个helper()函数,在helper()里面生成一个长度、内容都随机的数组,然后在main()函数里面把这个数组的内容打印出来。

helper() {
    创建一个数组
}

main() {
    helper();
    打印helper()函数中创建的数组
}

这里就需要用到结构体来保存创建数组的信息(头指针和长度):

#include<stdio.h>
#include <time.h>
#include<stdlib.h>


struct dynamic_arr {
    int *start;
    int size;
};

struct dynamic_arr *create_arr() {
    srand(time(NULL));
    int size = rand() % 10 + 1;

    int *arr = (int *) malloc((sizeof(int)) * size);
    if (!arr) return NULL;
    for (int i = 0; i < size; i++) {
        int rand_val = rand() % 20;
        *(arr + i) = rand_val;
        printf("create: %d\n", rand_val);
    }

    struct dynamic_arr *dy_arr = (struct dynamic_arr *) malloc(sizeof(struct dynamic_arr) * 1);
    dy_arr->start = arr;
    dy_arr->size = size;
    return dy_arr;

}

int main(int argc, char const *argv[]) {

    struct dynamic_arr *dy_arr = create_arr();
    if (dy_arr) {
        printf("----------\n");
        for (int i = 0; i < dy_arr->size; i++) {
            printf("get: %d\n", *(dy_arr->start + i));
        }
        free(dy_arr);
    } else {
        printf("error allocating\n");
    }
    return 0;
}

输出示例:

create: 0
create: 1
create: 3
create: 2
create: 5
create: 10
create: 8
----------
get: 0
get: 1
get: 3
get: 2
get: 5
get: 10
get: 8

C language Fibonacci

要解决的遗留问题

🔗 [C 语言实例 – 斐波那契数列 | 菜鸟教程] https://www.runoob.com/cprogramming/c-examples-fibonacci-series.html

遗留问题:写一个(高效率)recursion版本的fibonacci:

遇到的问题有:

1, recursion出现问题

🔗 [c++ - Using C-string gives Warning: "Address of stack memory associated with local variable returned" - Stack Overflow] https://stackoverflow.com/questions/18041100/using-c-string-gives-warning-address-of-stack-memory-associated-with-local-var

2, 无法像python那样返回类似tuple的数据结构

🔗 [How to make an array return type from C function? - Stack Overflow] https://stackoverflow.com/questions/14297169/how-to-make-an-array-return-type-from-c-function

🔗 [Returning an array using C - Stack Overflow] https://stackoverflow.com/questions/11656532/returning-an-array-using-c

开始解决上面提到的几个C语言问题

Fibonacci数列

本文所讲述的Fibonacci数列算法都仅仅局限于这个递归算法:

https://slideplayer.com/slide/5842639/

一段有问题的代码,这段代码在apple clang上面能跑通,但是linux gcc会抛出错误:

有问题的代码
//这段代码是有问题的

#include<stdio.h>

int *get_nth_Fibonacci_value_helper(int n) {

    if (n <= 1) {
        int val[2] = {n, 0};
        return val;
    } else {
        int *receive_val = get_nth_Fibonacci_value_helper(n - 1);
        int val[2] = {*receive_val + *(receive_val + 1), *receive_val};
        return val;
    }

}

int get_nth_Fibonacci_value(int n) {
    int *receive_val = get_nth_Fibonacci_value_helper(n);
    return *receive_val;
}


int main(int argc, char const *argv[]) {
    int N = 13;
    printf("%d th Fibonacci number is %d\n", N, get_nth_Fibonacci_value(N));
}

为什么这段代码会出问题?参考编译器给出的warning:

linux gcc

clang给的warning更清楚一些:

apple clang

为什么会出这个错误?因为 val 保存在stack,函数结束以后就会被销毁。(还是参考这个:🔗 [c++ - Using C-string gives Warning: "Address of stack memory associated with local variable returned" - Stack Overflow] https://stackoverflow.com/questions/18041100/using-c-string-gives-warning-address-of-stack-memory-associated-with-local-var

关于array在内存中的保存位置:

https://stackoverflow.com/questions/10696024/how-is-the-array-stored-in-memory

关于堆栈(以及static),参考:🔗 [Memory in C – the stack, the heap, and static – The Craft of Coding] https://craftofcoding.wordpress.com/2015/12/07/memory-in-c-the-stack-the-heap-and-static/

以下是两个示例程序:

程序1,gcc会报错:

// 这个程序会报错

#include<stdio.h>

int *try_to_get_arr_addr() {
    int val[3] = {0, 1, 2};
    return val;
}

int main(int argc, char const *argv[]) {
    printf("out of scope, val[0] is %d\n", *try_to_get_arr_addr());
}
程序2:这个程序确实能运行,但它会引发各种奇怪的问题,永远不要这样写!
#include<stdio.h>

int *try_to_get_arr_addr() {
    int val[3] = {111, 222, 333};
    int *p = &val[0];
    return p;
}

int main(int argc, char const *argv[]) {
    printf("out of scope, val[0] is %d\n", *try_to_get_arr_addr());
}

为什么说这个程序(或者说“return指向数组的指针”这样的写法)会出各种麻烦的问题?可以试着把指针p指向的地址多写一些:

(注意第11行:如果把第11行注释掉,那么大概率会得到结果111;如果留下第11行,那么大概率无法得到111)

#include<stdio.h>

int *try_to_get_arr_addr() {
    int val[3] = {111, 222, 333};
    int *p = &val[0];
    return p;
}

int main(int argc, char const *argv[]) {
    int *p = try_to_get_arr_addr();
    printf("print something\n");
    printf("out of scope, val[0] is %d\n", *p);
}

这种错误的写法写得越多就越容易搞出问题:

#include<stdio.h>

int *try_to_get_arr_addr() {
    int val[3] = {111, 222, 333};
    int *p = &val[0];
    return p;
}

int main(int argc, char const *argv[]) {
    int *p = try_to_get_arr_addr();
    printf("%d\n", *p);
    printf("%d\n", *p);
    printf("%d\n", *(p + 1));
    printf("%d\n", *(p + 1));
    try_to_get_arr_addr();
    printf("%d\n", *(p + 1));
}

这段程序用gcc, clang, msvc编译,得到的结果各不相同,因为C/C++无法保证什么时候一定会回收array占用的内存空间。

所以说“永远不要返回指向自动局部变量的指针” (中文《C语言程序设计 现代方法》 P367)

另外,一个非常好的社区问答:🔗 [c++ - Can a local variable's memory be accessed outside its scope? - Stack Overflow] https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope


所以回到Fibonacci问题,上面出错的程序修改后是能跑的:(注意要 free 

#include<stdio.h>
#include<stdlib.h>

int *get_nth_Fibonacci_value_helper(int n) {

    if (n <= 1) {
        int *val = (int *) malloc(sizeof(int) * 2);
        *val = 1;
        *(val + 1) = 0;
        return val;
    } else {
        int *receive_val = get_nth_Fibonacci_value_helper(n - 1);
//        int val[2] = {*receive_val + *(receive_val + 1), *receive_val};
        int *val = (int *) malloc(sizeof(int) * 2);
        *val = *receive_val + *(receive_val + 1);
        *(val + 1) = *receive_val;
        free(receive_val);
        return val;
    }

}

int get_nth_Fibonacci_value(int n) {
    int *receive_val = get_nth_Fibonacci_value_helper(n);
    return *receive_val;
}


int main(int argc, char const *argv[]) {
    int N = 13;
    printf("%d th Fibonacci number is %d\n", N, get_nth_Fibonacci_value(N));
}

运行结果:

13 th Fibonacci number is 233

当然,更合理的做法应该是“仅仅使用一开始就分配好的两个地址”,第一个地址存储F(N),第二个地址存储F(N-1):

#include<stdio.h>
#include<stdlib.h>


void get_fibonacci(int N, int *alloc_val) {
    // input: N, save two fibonacci series: F(N) and F(N-1) into *alloc_val
    if (N == 1) {
        *alloc_val = 1;
        *(alloc_val + 1) = 0;
        return;
    }
    get_fibonacci(N - 1, alloc_val);
    int Fn = *alloc_val + *(alloc_val + 1);
    int lastFn = *alloc_val;
    *alloc_val = Fn;
    *(alloc_val + 1) = lastFn;
}


int main(int argc, char const *argv[]) {
    int *alloc_val = (int *) malloc(2 * sizeof(int));
    int N = 13;
    get_fibonacci(N, alloc_val);
    printf("%d th Fibonacci number is %d\n", N, *alloc_val);
}

运行结果:

13 th Fibonacci number is 233

数组和指针

以下内容大纲均来自《C语言程序设计 现代方法》:通过复习书本,找出遗忘或者以前没接触过的内容。

两个指针相减

来自中文《C语言程序设计 现代方法》12.1.3

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[5] = {111, 222, 333, 444, 555};
    int *p = &arr[0];
    int *q = &arr[3];
    printf("*p - *q = %d\n", *p - *q);
    printf("p - q = %ld\n", p - q);
    return 0;
}

结果:

*p - *q = -333
p - q = -3

这样做是有限制条件的:

当然,malloc也可以,不要忘了 array 的定义:

Array is a type consisting of a contiguously allocated nonempty sequence of objects with a particular element type. The number of those objects (the array size) never changes during the array lifetime.

https://en.cppreference.com/w/c/language/array
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char const *argv[]) {
    int *addr = (int *) malloc(sizeof(int) * 4);
    int *p = addr;
    int *q = addr + 3;
    printf("*p - *q = %d\n", *p - *q);
    printf("p - q = %ld\n", p - q);
    return 0;
}

结果:

*p - *q = 0
p - q = -3

stack里相互赋值的变量是否会占用同一内存地址

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int i = 10;
    printf("%p\n", &i);
    int j = i;
    printf("%p\n", &j);
    int k = *&i;
    printf("%p\n", &k);
    return 0;
}

结果:

0x7ffc4199d10c
0x7ffc4199d108
0x7ffc4199d104

用const保护参数

来自中文《C语言程序设计 现代方法》P366

const放置位置是有讲究的:(详见中文《C语言程序设计 现代方法》P371)

void f(const int *p)     // “保护”了指针p指向的int
void f(int * const p)     // “保护”了指针p本身
void f(const int * const p)     // “保护”了指针p和指针p指向的int

但仍需注意,很多时候const的保护作用并没有其他语言那么强(可以认为是缺乏编译器的强制报错手段):

#include<stdio.h>

void helper(const int *const p) {
    printf("p是指针,指向了%d\n", *p);
    // p是指针,指向了10
    int *q = p;
    printf("现在q作为指针p的复制,指向的数值为%d\n", *q);
    // 现在q作为指针p的复制,指向的数值为10
    (*q)++;
    printf("现在q指向的数值为%d\n", *q);
    // 现在q指向的数值为11
}

int main(int argc, char const *argv[]) {
    int v = 10;
    int *p = &v;
    helper(p);
    printf("现在回到main(), v = %d\n", v);
    // 现在回到main(), v = 11
    return 0;
}

*运算符和++运算符的组合

来自中文《C语言程序设计 现代方法》P381

#include<stdio.h>

void print_arr(int *arr, int arr_size) {
    for (int i = 0; i < arr_size; i++) {
        printf("%d,", arr[i]);
    }
    printf("\n");
}

int main(int argc, char const *argv[]) {
    int arr[5] = {10, 20, 30, 40, 50};
    print_arr(arr, sizeof(arr) / sizeof(*arr));
    int *p = &arr[0];    // 一开始指向arr[0]
    *p++ = -1;    // 先把p指向的arr[0]赋值为-1,然后指针p向下移动1位指向arr[1]
    print_arr(arr, sizeof(arr) / sizeof(*arr));
    printf("step 1, 指针p现在指向的数字是:%d\n\n", *p);

    *++p = -5;    // 指针p原本指向arr[1],先把p向下移动1位指向arr[2],然后修改arr[2]的值为-5
    print_arr(arr, sizeof(arr) / sizeof(*arr));
    printf("step 2, 指针p现在指向的数字是:%d\n\n", *p);

    ++*p;    // 等同于++(*p);指针p原本指向arr[2],现在直接对*p(arr[2])的值+1
    print_arr(arr, sizeof(arr) / sizeof(*arr));
    printf("step 3, 指针p现在指向的数字是:%d\n\n", *p);

    (*p)++;    // 指针p原本指向arr[2],现在直接对*p(arr[2])的值+1
    print_arr(arr, sizeof(arr) / sizeof(*arr));
    printf("step 4, 指针p现在指向的数字是:%d\n\n", *p);

    return 0;
}

结果:

10,20,30,40,50,
-1,20,30,40,50,
step 1, 指针p现在指向的数字是:20

-1,20,-5,40,50,
step 2, 指针p现在指向的数字是:-5

-1,20,-4,40,50,
step 3, 指针p现在指向的数字是:-4

-1,20,-3,40,50,
step 4, 指针p现在指向的数字是:-3

实用主义程序:

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[5] = {10, 20, 30, 40, 50};
    int sum = 0;
    int *p = &arr[0];
    int N = sizeof(arr) / sizeof(*arr);
    while (p <= &arr[N - 1]) {
        sum += *p++;
    }
    printf("sum of arr is %d\n", sum);
    return 0;
}

得到:

sum of arr is 150

注意:这段程序的第8行引申出另一个话题,见下文:

一个引申问题

由上面的程序引申出的问题:

有一段程序:

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[5] = {10, 20, 30, 40, 50};
    int size_N = sizeof(arr) / sizeof(*arr);
    for (int i = 0; i < size_N + 10; i++) {    // 注意这一行明显超出了arr[]的界限
        printf("%p\n", &arr[i]);
    }
    return 0;
}

得到结果:

0x7ffc3250ada0
0x7ffc3250ada4
0x7ffc3250ada8
0x7ffc3250adac
0x7ffc3250adb0
0x7ffc3250adb4
0x7ffc3250adb8
0x7ffc3250adbc
0x7ffc3250adc0
0x7ffc3250adc4
0x7ffc3250adc8
0x7ffc3250adcc
0x7ffc3250add0
0x7ffc3250add4
0x7ffc3250add8

由此要注意C语言对数组越界的“不报错”。

所以之前的那段求和程序的第8行也可以写为:

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[5] = {10, 20, 30, 40, 50};
    int sum = 0;
    int *p = &arr[0];
    int N = sizeof(arr) / sizeof(*arr);
    while (p < &arr[N]) {    // 注意这里
        sum += *p++;
    }
    printf("sum of arr is %d\n", sum);
    return 0;
}

获取数组长度

以下两种写法都可以:

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[5] = {10, 20, 30, 40, 50};
    printf("size of arr is %lu\n", sizeof(arr) / sizeof(*arr));
    printf("size of arr is %lu\n", sizeof(arr) / sizeof(arr[0]));
    return 0;
}

得到结果:

size of arr is 5
size of arr is 5

获取作为参数传递的数组长度

🔗 [Find the Size of integer array received as an argument to a function in c - Stack Overflow] https://stackoverflow.com/questions/25680014/find-the-size-of-integer-array-received-as-an-argument-to-a-function-in-c

注意上面这张图的这句话:[ When you pass an array to a function, it decays into a pointer to the first element, at which point knowledge of its size is lost. ]

所以我们需要把arr_size也一并传过去:

#include<stdio.h>

void print_arr(int *arr, int arr_size) {
    for (int i = 0; i < arr_size; i++) {
        printf("%d,", arr[i]);
    }
}

int main(int argc, char const *argv[]) {
    int arr[5] = {10, 20, 30, 40, 50};
    print_arr(arr, sizeof(arr) / sizeof(*arr));
    return 0;
}

得到结果:

10,20,30,40,50,

sizeof的一些奇怪用法

见:🔗 [sizeof operator - cppreference.com] https://en.cppreference.com/w/c/language/sizeof

这个网页里有一个示范程序:

问题1:为什么sizeof 'a'会得到4(而不是1)?

🔗 [Size of character ('a') in C/C++ - Stack Overflow] https://stackoverflow.com/questions/2172943/size-of-character-a-in-c-c

反正目前死记结论就行了,结论:

另附上有用的程序1例:

另一个问题:

#include<stdio.h>

int main(int argc, char const *argv[]) {
    int arr[5] = {10, 20, 30, 40, 50};
    printf("sizeof(arr) = %lu\n", sizeof(arr));
    int *p = &arr[0];
    printf("sizeof(*p) = %lu\n", sizeof(p));
    printf("sizeof(arr[0]) = %lu\n", sizeof(arr[0]));
}

得到:

sizeof(arr) = 20
sizeof(*p) = 8
sizeof(arr[0]) = 4

那么,有没有什么代码,能够在arr创建后修改它的长度,使得sizeof(arr)返回一个更新过的结果?

当然是不行的,数组的长度一旦确定就永久不可改变:

🔗 [Array declaration - cppreference.com] https://en.cppreference.com/w/c/language/array

需要free数组吗?

并不需要,见:🔗 [How to free memory from char array in C - Stack Overflow] https://stackoverflow.com/questions/21513666/how-to-free-memory-from-char-array-in-c

用数组名作为指针

来自中文《C语言程序设计 现代方法》12.3

观察本文前面写的两句作用相同的程序语句:

    printf("size of arr is %lu\n", sizeof(arr) / sizeof(*arr));
    printf("size of arr is %lu\n", sizeof(arr) / sizeof(arr[0]));

这两句话的作用是等效的,由此可以很容易看出 *arr  arr[0] 之间的关系。

如果有数组 arr ,那么通常情况下:

1,  arr + i 等价于 &arr[i] 

2,   *(arr + i) 等价于 arr[i] .

但是要注意:

(a是数组)

数组作为参数传递的写法

本文之前有一段程序也可以写成这个样子(注意第3行)

#include<stdio.h>

void print_arr(int arr[], int arr_size) {    // 修改了这里!
    for (int i = 0; i < arr_size; i++) {
        printf("%d,", arr[i]);
    }
}

int main(int argc, char const *argv[]) {
    int arr[5] = {10, 20, 30, 40, 50};
    print_arr(arr, sizeof(arr) / sizeof(*arr));
    return 0;
}

参数里传递数组的两种写法 int arr[]  int *arr 是完全一样的,在《C语言程序设计 现代方法》P388有解释:

二维数组

由于本篇笔记在讨论C而不是C++,所以任何“传递int[][],返回int[][],传递int[][3],返回int[3][]...”这样的纠结都不存在了!我们只需要返回一个指向二维数组头部成员的指针就可以了。

总结:

int arr[5][3] = {{1, 2, 3},
                 {3, 4, 5},
                 {5, 6, 7},
                 {7, 8, 9},
                 {8, 9, 10},};
// 初始化一个5x3的二维数组


// 获取行数
int rows = sizeof(arr) / sizeof(arr[0]);
// rows = 5


// 获取列数
int cols = sizeof(arr[0]) / sizeof(arr[0][0]);
// cols = 3

example:

#include<stdio.h>
#include<string.h>

int main(int argc, char const *argv[]) {

    int arr[5][3] = {{1, 2, 3},
                     {3, 4, 5},
                     {5, 6, 7},
                     {7, 8, 9},
                     {8, 9, 10},};
    printf("sizeof(arr) = %lu\n", sizeof(arr));
    // sizeof(arr) = 60
    printf("sizeof(arr) / sizeof(int) = %lu\n", sizeof(arr) / sizeof(int));
    // sizeof(arr) / sizeof(int) = 15
    printf("sizeof(arr[0]) / sizeof(int) = %lu\n", sizeof(arr[0]) / sizeof(int));
    // sizeof(arr[0]) / sizeof(int) = 3
    printf("sizeof(arr) / sizeof(arr[0]) = %lu\n", sizeof(arr) / sizeof(arr[0]));
    // sizeof(arr) / sizeof(arr[0]) = 5
    printf("获取column时,sizeof(arr[0]) / sizeof(int) 最好写成 sizeof(arr[0]) / sizeof(arr[0][0]): %lu\n",
           sizeof(arr[0]) / sizeof(arr[0][0]));
    // 获取column时,sizeof(arr[0]) / sizeof(int) 最好写成 sizeof(arr[0]) / sizeof(arr[0][0]): 3

    int cols = sizeof(arr[0]) / sizeof(arr[0][0]);
    int rows = sizeof(arr) / sizeof(arr[0]);

    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            printf("%d ", arr[r][c]);
        }
        printf("\n");
    }
    return 0;
}

运行结果:

sizeof(arr) = 60
sizeof(arr) / sizeof(int) = 15
sizeof(arr[0]) / sizeof(int) = 3
sizeof(arr) / sizeof(arr[0]) = 5
获取column时,sizeof(arr[0]) / sizeof(int) 最好写成 sizeof(arr[0]) / sizeof(arr[0][0]): 3
1 2 3 
3 4 5 
5 6 7 
7 8 9 
8 9 10 

OCR辅助查找工具

A Better Fibonacci Algorithm Use linear recursion instead: Algorithm LinearFibonacci(k): Input: A nonnegative integer k Output: Pair of Fibonacci numbers (Fo Fki) if k = 1 then return (k, O) else (i, j) := LinearFibonacci(k 1) return (i+, i) Linear recursion: a method makes at most one recursive call each time it is invoked. Runs in O(k time. test.c: In function ‘get nth_ Fibonaccivalue_ helper’: test.c:9:16: warning: function returns address of local variab le [-Wreturn-Local-addr] return val; ^An test.c:13:16: warning: function returns add ress of local variable [-Wreturn-Local-addr] return val; ^AN Segmentation fault 2.c:9:16: warning: address of stack memory associated with Local variable val’ returned [-Wreturn-stack-address] return val; ^NN 2.c:13:16: warning: address of stack memory associated with Local variable ‘val’ returned 「-Wreturn-stack-address] return val; ^Nn 2 warnings generated. 13 th Fibonacci number is 233 A local array will be (usually) created on stack while • A global or static array will be (usually) created on bss/data segments and • A dynamically created array will be created on heap. A永远不要返回指向自动局部变量的指针: int *f (void) int i; return &i; 一旦f返回,变量讠就不存在了,所以指向变量讠的指针将是无效的。有的编译器会在这种情况下给出类似“function returns address of local variable”的警告。 A在一个不指向任何数组元素的指针上执行算术运算会导致未定义的行为。此外,只有在两个指针指向同一个数组时,把它们相减才有意义。用const保护参数当调用函数并且把指向变量的指针作为参数传入时,通常会假设函数将修改变量(否则,为什么函数需要指针呢?)。例如,如果在程序中看到语句 f(&x); 大概是希望f改变x的值。但是,f仅需要检查x的值而不是改变它的值也是可能的。指针可能高效的原因是:如果变量需要大量的存储空间,那么传递变量的值会浪费时间和空闻。(12.3节会更详细地介绍这方面内容。) Q&A可以使用单词const来表明函数不会改变指针参数所指向的对象。const应放置在形式参数的声明中,后面紧跟着形式参数的类型说明: void f (const int *p) ~ pp三0; /大大 WRONG 大, 这一用法表明p是指向“常整数”的指针。试图改变p是编译器会检查的一种错误。 C程序员经常在处理数组元素的语句中组合(间接寻址)运算符和++运算符。思考一个简单的例子:把值存入一个数组元素中,然后前进到下一个元素。利用数组下标可以这样写: a[i++] = j; 如果p指向数组元素,那么相应的语句将会是 p++ = j; 因为后缀++的优先级高于,所以编译器把上述语句看成是 (p++) 」 p++的值是p。(因为使用后缀++,所以p只有在表达式计算出来后才可以自增。)因此,(p++)的值将是p,即p当前指向的对象。 You cannot do it that way. When you pass an array to a function, it decays into a pointer to the first element, at which point knowledge of its size is lost. If you want to know the size of an array passed to the function, you need to work it out before decay and pass that information with the array, something like: void function (size_t sz, int arr) { • } { int x[20]; } function (sizeof(x) /sizeof(x),x): Example sample output corresponds to a platform with 64-bit pointers and 32-bit int Run this code #include int main (void) { short X; // type argument: printf(“sizeof(float)三%zuln”, sizeof(float)); printf(“sizeof (void() (void))二Szuln”, sizeof(void() (void))); printf(“sizeof (char [10]) %zuln”, sizeof(char[10])); // printf(“sizeof (void (void))三%zuln”, sizeof (void (void)));// Error: function type / printf(“sizeof (char[])二9zuln”, sizeof(char[])); // Error: incomplete type // expression argument: printf(“sizeof ‘a’二%zuln” Sizeof ‘a”);// type of ‘a’ is int // printf(“sizeof main = %zuln”,sizeof main); // Error: Function type printf(“sizeof &main二Szuln” sizeof smain); printf( “sizeof \”hellol”三%zuln” sizeof “helLo”); // type is char[6] printf( “sizeof X = %zuln”, sizeof x); // type of x is short printf(“sizeof (x+1) = %zuln”, sizeof(x+1));/! type of x+1 is int ~ Possible output: Sizeof(float) Sizeof (void() (void)) sizeof(char[10])三10 Sizeof ‘a’ Sizeof &main Sizeof “hello” = sizeof X寸0H寸ooN Sizeof (x+1) 4 In C, the type of a character constant like ‘a’ is actually an int, with size of 4 (or some other implementation-dependent value). In C++, the type is char, with size of 1. This is one of many small differences between the two languages. In C: #incLude int main() { char a =‘a; printf(“Size of char %d\n”, sizeof(a)); printf(“Size of char %din”, sizeof(‘a’)); return 0;冖 Output: Size of char Size of char H寸C C language Declarations Array declaration Array is a type consisting of a contiguously allocated nonempty sequence of objects with a particular element type. The number of those objects (the array size) never changes during the array lifetime. A虽然可以把数组名用作指针,但是不能给数组名赋新的值。试图使数组名指向其他地方是错误的: while(a != 0) a++; /大WRONG ***/下形式定义find largest函数: M如果需要,可以把数组型形式参数声明为指针。例如,可以按如 int find largest (int *a, int n) 作是完全一样的。声明a是指针就相当于声明它是数组。EM编译器把这两类声明看


 Last Modified in 2023-02-18 

Leave a Comment Anonymous comment is allowed / 允许匿名评论