C語言為何不改進數組?

realloc


檢查超越邊界的事情交給程序員,都給編譯器會大大降低執行效率。malloc, calloc, recalloc用起來~


用動態內存分配

realloc


用C編寫有限元程序,我猜題主面臨的一個主要技術難點應該是向函數傳遞矩陣的問題。

毋庸諱言,原始的C語言在這一點上確實非常蹩腳,但解決問題的辦法還是有的,只是需要對C語言有很深的了解並需要採用一些不常用到的語言技巧。

C99之後這個問題已經很好地解決了。FORTRAN語言的那些演算法基本可以直接搬過去就能用——這正是C99要達到的目的之一。

所以現代C語言已經不存在題主所說的那種「硬傷」了。當然,如果題主不懂得現代的、新的C語言那就是另一回事了。


C本身不行,但是C的庫行啊。

nothings/stb

推薦一下神庫stb,學圖形學的應該對這個庫里的stb_image.h 印象深刻,用過openAL可能還用用 stb_vorbis.c ,可能部分人還用過他的 stb_truetype.h 來代替臃腫的freetype2 ...

但這個庫里提供的 stretchy_buffer.h 可能知道的人少些,這是個C語言的動態數組,核心代碼不到20行,去掉注釋的LOC只有257個字元。新手完全可以通過這個庫學習設計自己的C vector


設計者可能考慮到靜態的速度要好過動態


1,C語言中有一個函數malloc,動態分配內存,可以滿足題主的要求。

比如你要生成一個長度為10的int數組,直接用int *p = (int *)malloc(10*sizeof(int)),當你想重新改變數組長度時,可以用realloc函數。

當然你得#include &

2,C99標準允許用戶使用變長數組

比如

int n;

scanf("%d",n);

int array[n];

這樣也很簡單

3,C++中可以用STL中的vector容器啊

# include &

vector & v;

利用push_back()和pop_back()函數,你可以自由地向容器尾部裡面添加或刪除元素

4,Python大法好

利用append方法和+運算,你可以隨心所欲地向列表裡面添加元素


用python吧,數組不僅自增長,而且啥都能往裡面放


... malloc

Array copy

別的我不知道,Java的Linkedlist和ArrayList 分別用了這兩種思路,你覺得變長數組很高端么?


不會自己分配內存嗎


C 的數組似乎是被作為變數分配在棧裡面,如果要在棧內支持動態調整時間複雜度可觀。還不如直接在堆里 alloc 一堆內存出來,在棧裡面聲明個指針指過去比較方便 ⊙_⊙


請使用動態分配或鏈表,要不你就使用C++的模板.

指定大小直接聲明數組在實際工作中比較少用,要不就是偷懶.

一般臨時使用一下,不要太大,超出堆棧就崩了.

現在的機器內存是比較大,但是也會用完的啊.虛擬內存好使,但不停的交換也是很慢的.

使用演算法,不要去埋怨語言或系統.


問這個問題之前,先問一下自己,這裡邊有兩個變數,一個是初始化數組,另外一個增量,你覺得,初始化數組設多大合適,另外一個增量,設計多大合適,如果兩個答案都沒有完美的答案的話,c語言就是干這個事情的,另外一個增量在很多時候,還不是一個常量,還會變化,這個又複雜了


很贊同前面大牛說的C語言的設計貼近硬體底層,我這裡再補充一下。

C語言在語言層面,不會提供太多超過硬體原始表達能力的概念。

數組的長度,只是編譯器為數組在棧上分配空間用到,運行時已經丟失了這個信息。

寫個簡單的例子:

#include &

void print(int* a, int len)
{
int i = 0;
for (; i &< len; i++) { printf("%d ", a[i]); } } int main() { int a[100]; a[1] = 999; print(a, 2); }

看看在彙編裡面的表示:

main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $400, %rsp
movl $999, -396(%rbp)
leaq -400(%rbp), %rax
movl $2, %esi
movq %rax, %rdi
call print
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc

最重要看到這一句:

subq $400, %rsp

這裡在棧上分配400個位元組的空間,也就是sizeof(int) * 100。

這個就是數組在運行時的實體了,這個長度是不會被編譯器用某些形式(例如變數)保存下來的,所以程序員寫代碼時要自己找地方保存,以便後續引用。很自然,編譯器也不會檢查對數組的越界訪問。

要將原始數組封裝為數組對象來訪問,那不是C語言在語言層面的事情,而是開發某個庫來實現的事情,例如glib。有些語言選擇在語言層面提供數組對象,例如Python的list(例如生成list就是用位元組碼來表示的,所以我稱之為語言層面,當然list的更多操作在標準庫裡頭實現),是因為Python的定位是快速開發而忽略底層細節(自然也損失了一定的運行性能)。


樓主是半吊子的學習者,c語言對於動態數組支持的很好,指針+malloc就很方便的解決。有人提到矩陣傳遞參數的問題,這算問題嗎?c語言值傳遞可以屏蔽參數,避免修改,指針傳遞需要修改的參數,多方便啊。


我什麼時候說會出現runtime error ?

我說得很清楚 你的代碼是錯的 聽不懂 ?

我說 哪怕運行結果符合你的預期 代碼依然是錯的 聽不懂 ?

說了很清楚 你的代碼錯的是踩到未定義行為這條線了

錯的是代碼 你扯什麼runtime

這就是你注釋裡面要的輸出 呵呵

這就是你注釋裡面要的輸出 呵呵世界很大 非要我打臉嗎? @藍色鼓點


有限元程序貌似應該是直接賦出來一個超級大的數組然後把數據都放在裡面做.....這樣的話速度會快.....至少fortran能應該這麼做....前面什麼說鏈表的,是不是都不知道有限元是什麼。。。


事實上,C語言根本沒有什麼數組,它只是規定了一個下標訪問數據的語法而已,然後人們以訛傳訛的說這就是數組。

你要高級數組自己寫個就好了,更別說一堆的人幫你寫了各種高級的數組。


如果你想直接用的話,換一個支持動態大小的語言就好了,比如有List的。

C就是這麼底層。


推薦閱讀:

Lisp 和 Haskell 各有什麼優缺點?學哪個好?
C# 兩種遍歷列表的方式,哪種更高效?
為什麼數據分析需要會編程語言?
為什麼很多語言中,要用三個引號或其他符號來表示多行字元串字面量?
關於 Type Inference 的各種應用和學習資料?

TAG:編程語言 | C編程語言 |

分頁阅读: 1 2