0%

C语言 main函数

聊聊main函数

main字面的意思就是主要的意思,在程序里面也是,并且更重要了,是主函数,何为主函数,就是程序运行会执行的第一个程序,意即程序的入口,如果说眼睛是心灵的窗户,那么main就是程序的大门。

在C99标准之前,main函数可以没有返回类型或者使用void,如下所示:

1
2
3
4
5
/*beginner/main/main1.c*/

main()
{
}

或者

1
2
3
4
5
6
/*beginner/main/main2.c*/

void main()
{
}

这两个可以称为最短小精悍的程序了,不会出错,因为没有语句。

如果使用C99标准编译,就可以看到如下的警告信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
main1.c:3:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main()
^
1 warning generated.
gcc -o main2 main2.c
main2.c:3:1: warning: return type of 'main' is not 'int' [-Wmain-return-type]
void main()
^
main2.c:3:1: note: change return type to 'int'
void main()
^~~~
int
1 warning generated.

警告的含义就是我们的mian函数是有血有肉的,是有正儿八经的返回值的,这个返回值的类型就是int,所以这个程序:

1
2
3
4
5
/*beginner/main/main3.c*/

int main()
{
}

OK,完美编译,没有任何报错信息,不过终归看着少了点什么,是的,如果定义了返回类型,就需要有相应的返回,所以第一个标准的简单C语言函数如下所示:

1
2
3
4
5
6
/*beginner/main/main4.c*/

int main()
{
return 0;
}

main函数的形式

恩,既然写出了main函数的标准形式,这里就需要讨论一个问题,为什么有时候看到int main(),有时候又看到int main(int argc, char *argv[])呢,具体的形式如下所示:

无参数的main函数

1
2
3
4
5
6
7
8
/*beginner/main/main5.c*/

int main()
{
printf("Hello World\n");
return 0;
}

可以看到上面这个例子,只是打印了hello world,并没有其他语句。

而下面的例子,我们看到使用到了argc和argv,所谓的形参,所以在有需要的时候才会出现这种形式,就好像是黄蓉给郭靖的几个锦囊^_^。

有参数的main函数

1
2
3
4
5
6
7
8
9
10
11
12
/*beginner/main/main6.c*/

int main(int argc, char *argv[])
{
printf("The are %d arguments.\n", argc);
int i;
for (i = 0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
return 0;
}

编译运行

直接输入make就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#beginner/main/Makefile
ALL : main1 main2 main3 main4 main5 main6

main1: main1.c
gcc -o main1 main1.c

main2: main2.c
gcc -o main2 main2.c

main3: main3.c
gcc -o main3 main3.c

main4: main4.c
gcc -o main4 main4.c

main5: main5.c
gcc -o main5 main5.c

main6: main6.c
gcc -o main6 main6.c

.PHONY : clean

clean:
rm -f main1 main2 main3 main4 main5 main6

MALLOC(3) Linux Programmer’s Manual MALLOC(3)

NAME
malloc, free, calloc, realloc - allocate and free dynamic memory

SYNOPSIS
#include <stdlib.h>

   void *malloc(size_t size);
   void free(void *ptr);
   void *calloc(size_t nmemb, size_t size);
   void *realloc(void *ptr, size_t size);
   void *reallocarray(void *ptr, size_t nmemb, size_t size);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

   reallocarray():
       Since glibc 2.29:
           _DEFAULT_SOURCE
       Glibc 2.28 and earlier:
           _GNU_SOURCE

DESCRIPTION
The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique
pointer value that can later be successfully passed to free().

   The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc(), or realloc().  Otherwise, or if free(ptr) has al‐
   ready been called before, undefined behavior occurs.  If ptr is NULL, no operation is performed.

   The  calloc()  function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory.  The memory is set to zero.  If nmemb or size
   is 0, then calloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().  If the multiplication of nmemb and size would  result  in  integer
   overflow, then calloc() returns an error.  By contrast, an integer overflow would not be detected in the following call to malloc(), with the result that an incorrectly sized block of
   memory would be allocated:

       malloc(nmemb * size);

   The realloc() function changes the size of the memory block pointed to by ptr to size bytes.  The contents will be unchanged in the range from the start of the region up to the  mini‐
   mum of the old and new sizes.  If the new size is larger than the old size, the added memory will not be initialized.  If ptr is NULL, then the call is equivalent to malloc(size), for
   all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr).  Unless ptr is NULL, it must have been returned by an earlier call to mal‐
   loc(), calloc(), or realloc().  If the area pointed to was moved, a free(ptr) is done.

   The reallocarray() function changes the size of the memory block pointed to by ptr to be large enough for an array of nmemb elements, each of which is size bytes.  It is equivalent to
   the call

           realloc(ptr, nmemb * size);

   However, unlike that realloc() call, reallocarray() fails safely in the case where the multiplication would overflow.  If such an overflow occurs, reallocarray()  returns  NULL,  sets
   errno to ENOMEM, and leaves the original block of memory unchanged.

RETURN VALUE
The malloc() and calloc() functions return a pointer to the allocated memory, which is suitably aligned for any built-in type. On error, these functions return NULL. NULL may also
be returned by a successful call to malloc() with a size of zero, or by a successful call to calloc() with nmemb or size equal to zero.

   The free() function returns no value.

   The realloc() function returns a pointer to the newly allocated memory, which is suitably aligned for any built-in type, or NULL if the request failed.  The returned  pointer  may  be
   the  same as ptr if the allocation was not moved (e.g., there was room to expand the allocation in-place), or different from ptr if the allocation was moved to a new address.  If size
   was equal to 0, either NULL or a pointer suitable to be passed to free() is returned.  If realloc() fails, the original block is left untouched; it is not freed or moved.

   On success, the reallocarray() function returns a pointer to the newly allocated memory.  On failure, it returns NULL and the original block of memory is left untouched.

ERRORS
calloc(), malloc(), realloc(), and reallocarray() can fail with the following error:

   ENOMEM Out of memory.  Possibly, the application hit the RLIMIT_AS or RLIMIT_DATA limit described in getrlimit(2).

ATTRIBUTES
For an explanation of the terms used in this section, see attributes(7).

   ┌─────────────────────┬───────────────┬─────────┐
   │Interface            │ Attribute     │ Value   │
   ├─────────────────────┼───────────────┼─────────┤
   │malloc(), free(),    │ Thread safety │ MT-Safe │
   │calloc(), realloc()  │               │         │
   └─────────────────────┴───────────────┴─────────┘

CONFORMING TO
malloc(), free(), calloc(), realloc(): POSIX.1-2001, POSIX.1-2008, C89, C99.

   reallocarray() is a nonstandard extension that first appeared in OpenBSD 5.6 and FreeBSD 11.0.

NOTES
By default, Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. In case
it turns out that the system is out of memory, one or more processes will be killed by the OOM killer. For more information, see the description of /proc/sys/vm/overcommit_memory and
/proc/sys/vm/oom_adj in proc(5), and the Linux kernel source file Documentation/vm/overcommit-accounting.rst.

   Normally, malloc() allocates memory from the heap, and adjusts the size of the heap as required, using sbrk(2).  When allocating blocks of memory larger than MMAP_THRESHOLD bytes, the
   glibc  malloc()  implementation  allocates the memory as a private anonymous mapping using mmap(2).  MMAP_THRESHOLD is 128 kB by default, but is adjustable using mallopt(3).  Prior to
   Linux 4.7 allocations performed using mmap(2) were unaffected by the RLIMIT_DATA resource limit; since Linux 4.7, this limit is also enforced for allocations performed using mmap(2).

   To avoid corruption in multithreaded applications, mutexes are used internally to protect the memory-management data structures employed by these functions.  In a multithreaded appli‐
   cation  in  which  threads  simultaneously  allocate and free memory, there could be contention for these mutexes.  To scalably handle memory allocation in multithreaded applications,
   glibc creates additional memory allocation arenas if mutex contention is detected.  Each arena is a large region of memory that is internally allocated by the system (using brk(2)  or
   mmap(2)), and managed with its own mutexes.

   SUSv2 requires malloc(), calloc(), and realloc() to set errno to ENOMEM upon failure.  Glibc assumes that this is done (and the glibc versions of these routines do this); if you use a
   private malloc implementation that does not set errno, then certain library routines may fail without having a reason in errno.

   Crashes in malloc(), calloc(), realloc(), or free() are almost always related to heap corruption, such as overflowing an allocated chunk or freeing the same pointer twice.

   The malloc() implementation is tunable via environment variables; see mallopt(3) for details.

SEE ALSO
valgrind(1), brk(2), mmap(2), alloca(3), malloc_get_state(3), malloc_info(3), malloc_trim(3), malloc_usable_size(3), mallopt(3), mcheck(3), mtrace(3), posix_memalign(3)

   For details of the GNU C library implementation, see ⟨https://sourceware.org/glibc/wiki/MallocInternals⟩.

COLOPHON
This page is part of release 5.05 of the Linux man-pages project. A description of the project, information about reporting bugs, and the latest version of this page, can be found at
https://www.kernel.org/doc/man-pages/.

GNU 2020-02-09 MALLOC(3)

处无为之事,行不言之教;作而弗始,生而弗有,为而弗恃,功成不居!

欢迎关注我的其它发布渠道