Skip to content

Commit 1ba1034

Browse files
committed
posix split execl
1 parent 74e873f commit 1ba1034

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+891
-153
lines changed

c/compound_struct_literal.c

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ int main() {
3838
assert(sp->i == 1);
3939
assert(sp->j == 2);
4040

41+
/* Unlike string literals, they can be modified. */
42+
sp->i = 3;
43+
sp->j = 4;
44+
assert(sp->i == 3);
45+
assert(sp->j == 4);
46+
4147
/*
4248
# Lifetime of compound struct literals
4349

c/generic.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,20 @@
88

99
int main() {
1010
#if __STDC_VERSION__ >= 201112L
11-
#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 9
11+
#if defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))
1212
#define typename(x) _Generic((x), \
1313
int: "int", \
1414
float: "float", \
1515
default: "other")
1616

1717
int i;
18+
const int ci;
1819
float f;
1920
void* v;
2021
assert(strcmp(typename(i), "int") == 0);
22+
assert(strcmp(typename(ci), "int") == 0);
2123
assert(strcmp(typename(f), "float") == 0);
22-
assert(strcmp(typename(i), "other") == 0);
24+
assert(strcmp(typename(v), "other") == 0);
2325
#endif
2426
#endif
2527
}

c/null.c

+118-24
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,156 @@
11
/*
2-
# NULL
2+
# null pointer constant
33
4-
Good source: <http://c-faq.com/null/macro.html>
4+
Good source: http://c-faq.com/null/macro.html
55
66
Basic usage: indicate error as return value from function
7+
8+
C99 7.17/3 Common definitions `<stddef.h>` says:
9+
10+
# NULL
11+
12+
> NULL: macro which expands to an implementation-defined null pointer constant;
13+
14+
Then form the definition of "null pointer constant", it is either of:
15+
16+
- `0`
17+
- `(void*)0`
18+
19+
Thus in x86-64, is it possible to differentiate them by size:
20+
`0` is 4 bytes, while `(void*)` is 8.
21+
22+
C++:
23+
24+
- ensures that NULL is an "rvalue of integer type that evaluates to zero" (`0`):
25+
it cannot be a pointer.
26+
27+
- introduces the related `nullptr`, which is guaranteed to be a pointer type.
28+
29+
This is specially important because of function overload.
30+
31+
# Null pointer constant
32+
33+
# Null pointer
34+
35+
Null pointer constant and null pointer are note the same thing!!!
36+
37+
6.3.2/3 Pointers:
38+
39+
> An integer constant expression with the value 0, or such an expression cast to type
40+
void *, is called a null pointer constant.55) If a null pointer constant is converted to a
41+
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
42+
to a pointer to any object or function.
43+
44+
6.3.2/4 Pointers:
45+
46+
> Conversion of a null pointer to another pointer type yields a null pointer of that type.
47+
Any two null pointers shall compare equal.
48+
49+
Therefore there are multiple `null` pointer types: `(void *)0`, `(int *)0`, etc.
50+
51+
# argc[argv]
52+
53+
Null pointer
54+
55+
5.1.2.2.1/2 Program startup:
56+
57+
> argv[argc] shall be a null pointer.
758
*/
859

960
#include "common.h"
1061

62+
int *ip;
63+
1164
int main() {
1265
/*
13-
Why it works: it never points to any possible valid memory location.
14-
(`&` operator never gives anything equal to it).
15-
this is so guaranteed that gcc emmits a warning in the following code
66+
It never points to any possible valid memory location:
67+
global, local variable, malloc return, ...
68+
69+
In other words, taking `&` of a variable never gives it.
1670
*/
1771
{
1872
int i = 0;
1973
/* WARN GCC 4.7 warning: &i will never be null. Smart. */
2074
/*assert(&i != NULL);*/
2175
}
2276

23-
/* How it prints like: */
24-
printf("NULL = %p\n", NULL);
77+
/*
78+
How it prints like: implementation defined.
2579
26-
/* `if(NULL)` and `if(!NULL)` in error checking code always work as expected */
27-
assert(!NULL);
80+
C99 7.19.6.1/8 The fprintf function:
81+
82+
> `p`: The argument shall be a pointer to void. The value of the pointer is
83+
converted to a sequence of printing characters, in an implementation-defined
84+
manner.
85+
*/
86+
{
87+
printf("printf NULL %%p = %p\n", NULL);
88+
}
2889

2990
/*
30-
# NULL macro vs 0
91+
# == for null pointers
3192
32-
Relationship to 0: typecasting `(int)0` to any pointer type as
33-
`(int*)0`, `(char*)0` always gives NULL.
93+
Treated specially at 6.5.9/5 Equality operators:
3494
35-
This is a valid way of representing the NULL pointer,
36-
but it is better style to always use the `NULL` macro
95+
> If one operand is a pointer and the other is a
96+
null pointer constant, the null pointer constant is converted to the type of the pointer.
3797
38-
The exact definition of `NULL` is implementation dependant.
39-
A very common implementation is as `(void*)0`.
98+
And 6.5.9/6:
4099
41-
C++11 also introduces the related `nullptr`.
100+
> Two pointers compare equal if and only if both are null pointers, [...]
42101
*/
43102
{
44-
assert(NULL == (int*)0);
45-
assert(NULL == (char*)0);
46-
printf("sizeof(NULL) = %zu\n", sizeof(NULL));
103+
/*
104+
True, since both are null pointers.
105+
106+
TODO error or warning? WARN GCC 4.8: comparison of distinct pointers without cast.
107+
*/
108+
{
109+
/*assert((char *)0 == (int *)0);*/
110+
}
111+
112+
/*
113+
True: one is a pointer, and the other is a null pointer constant.
114+
*/
115+
{
116+
assert((char *)0 == NULL);
117+
118+
/* Above is converted to: */
119+
assert((char *)0 == (char *)NULL);
120+
121+
/* True because `0` is a null pointer constant: */
122+
assert((char *)0 == 0);
123+
124+
/*
125+
True because NULL is either:
126+
127+
- `0`
128+
- `(void *)0`, which is a null pointer constant
129+
*/
130+
assert(NULL == 0);
131+
}
132+
133+
/*
134+
As a consequence, if(p) can be used directly on null checks,
135+
as it is equivalent to:
136+
137+
if (p != 0)
138+
*/
139+
{
140+
if (NULL)
141+
assert(false);
142+
}
47143
}
48144

49-
/* ERROR: comparison of distinct pointer types requires a cast: */
145+
/* WARN: comparison of distinct pointer types requires a cast: */
50146
{
51147
/*assert((int*)0 == (char*)0);*/
52148
}
53149

54150
/*
55151
Never dereference the NULL pointer since it is guaranteed to point to nothing.
56152
57-
TODO to ANSI C, undefined behaviour? or guaranteed error?
58-
59-
May lead to a Segmentation fault.
153+
TODO Undefined behaviour? On Linux leads to a Segmentation fault.
60154
*/
61155
{
62156
/*volatile int i = *(int*)NULL;*/

c/offsetof.c

+24-11
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,30 @@
1212
#include "common.h"
1313

1414
int main() {
15-
struct foo {
16-
char a;
17-
char b[2];
18-
int c;
19-
char d;
20-
};
21-
22-
printf("offsetof(struct foo, a) = %zu\n", offsetof(struct foo, a));
23-
printf("offsetof(struct foo, b) = %zu\n", offsetof(struct foo, b));
24-
printf("offsetof(struct foo, c) = %zu\n", offsetof(struct foo, c));
25-
printf("offsetof(struct foo, d) = %zu\n", offsetof(struct foo, d));
15+
/* Basic example. */
16+
{
17+
struct S {
18+
char a;
19+
char b[2];
20+
int c;
21+
char d;
22+
};
23+
24+
printf("a = %zu\n", offsetof(struct S, a));
25+
printf("b = %zu\n", offsetof(struct S, b));
26+
printf("c = %zu\n", offsetof(struct S, c));
27+
printf("d = %zu\n", offsetof(struct S, d));
28+
}
29+
30+
/* Does not work with bitfields. */
31+
{
32+
struct S {
33+
int a:1;
34+
};
35+
36+
/* ERROR: attempt to take the address of a bitfield struct member. */
37+
/*printf("a = %zu\n", offsetof(struct S, a));*/
38+
}
2639

2740
return EXIT_SUCCESS;
2841
}

c/operator.c

+16-1
Original file line numberDiff line numberDiff line change
@@ -301,13 +301,28 @@ int main() {
301301
/*
302302
# &
303303
304-
AND bitwise
304+
AND bitwise
305+
306+
# |
307+
308+
OR bitwise
305309
*/
306310
{
307311
assert(((char)0x00 & (char)0x00) == (char)0x00);
308312
assert(((char)0xFF & (char)0x00) == (char)0x00);
309313
assert(((char)0xFF & (char)0xFF) == (char)0xFF);
310314

315+
/*
316+
`&` and `|` have lower precedence than `==`!
317+
318+
Notorious design choice, since they are analogous to + and * ...
319+
*/
320+
{
321+
assert(!(2 & 0 == 0 ));
322+
assert(!(2 & (0 == 0)));
323+
assert( (2 & 0) == 0 );
324+
}
325+
311326
/*
312327
# Even
313328

c/static/variable/main.c

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ static int si = 0;
66
void a();
77

88
void m() {
9+
j = i;
910
i++;
1011
si++;
1112
puts("m()");

c/stdio_h.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ int main() {
769769
- SEEK_END: relative to end of file
770770
771771
It seems that seeking after the eof is undefined behaviour in ANSI C:
772-
<http://bytes.com/topic/c/answers/219508-fseek-past-eof>
772+
http://bytes.com/topic/c/answers/219508-fseek-past-eof
773773
774774
This contrasts with POSIX lseek + write, in which the unwriten gap is 0.
775775
*/

0 commit comments

Comments
 (0)