I do a lot of work in various languages, most of which are scripting languages such as JavaScript, Shell Scripting, PHP and so on. But I do also work a lot with Java, which is closer to a more "real" language.

C/C++ has been an interest always, but have not had much use for it. I did have a few small things in some Java projects that needed to be delegated to a faster solution, mostly when dealing with a lot of file operations. For this I used C++ because it has some abstractions like string and such that let me avoid most of C's pointer styles "*".

But I did not really get all into C++, just read what I needed to make it work. And doing something without knowing fully what you are doing, can cause problems. For example, it's easy to create memory leaks without getting any problems with the compiler. Just because something compiles and runs, does not mean that it does not have problems.

So now I have decided to spend some time with this properly. And not C++, because you are still engaging C a lot of the time, so better to understand that one first, before starting with the other.

For the most part C is easy enough. What I find problematic is the pointers. I know what pointers is. But in most languages you work with references and not with pointers directly, so it is giving me a few headaches figuring out exactly what I am dealing with some times.

Example

char *cvar;
cvar = "";
*cvar = "";

In the above example, I believe the first one is correct? The second one tries to change the pointer and not the content?

char *cvar = "";

But if that's the case, why is this then correct? Does the literals return values or pointers? Cause it seams as if it varies or I am mistaken about when I work with values or pointers.

function name(char *arg) {
}
name(&cvar);

C passes by value, so what do I get in the function? Copied pointer that points to the same place/value?

But if that's the case, why is this then correct? -- Because char *cvar = ""; is both a declaration and an assignment, not just an assignment. You would never refer to an already-declared variable using "pointer to" (*) notation.
– Robert Harvey♦Apr 13 '18 at 21:26

so what do I get in the function? -- You get a character identified by arg, stored in a memory location scoped outside of the function.
– Robert Harvey♦Apr 13 '18 at 21:29

1 Answer
1

For C declarations, we need to distinguish between arrays and pointers.

Arrays reserve storage for their elements, and an array references are treated like a pointer values (to their first element) anytime they are used in an expression.

char *cvar;

The preceding declares the identifier as a pointer, and reserves storage for that pointer; the pointer is otherwise uninitialized. In a global context this storage will get zeroed out (modulo initialization in another compilation unit). In a local context, the storage goes uninitialized (i.e. has garbage). This declaration does not involve an array.

cvar = "hello world\n";

The preceding does two things:

first, it adds a terminating null to the string literal, and then allocates an array for the string literal: "hello world\n\0". The allocation for such literals is always static, i.e. it becomes an initialized constant byte/char array in the global space (regardless of the context of the string literal's usage).

second, upon execution if local, or primordially, if global, assignment itself puts the address of that static string literal byte array's first element into the pointer variable.

*cvar = "hi";

This above nonsensical, as it is a type mismatch. *cvar represents a single char: the one pointed to by cvar. An array-of-char, the string literal, "hi\0", becomes a pointer-to-char in the expression context — and we cannot assign a pointer-to-char to a single char (it won't fit plus its a type mismatch). (Further, note that the pointer value in cvar is uninitialized (or initialized in some context not shown).)

I believe the first one is correct?

Yes

The second one tries to change the pointer and not the content?

No, it tries to use the pointer to change what is being pointed to.

why is this then correct?

Because it is simply the combination of your first two statements, written as one.

Does the literals return values or pointers?

Both, sort of. Literals are initialized byte arrays, which convert to pointers to the first element (in usage, just like all arrays). Informally, pointers are the variables that hold addresses, and addresses are values that can be used in expressions (as long as types properly match) just like integers.

C parses[sic: "passes"] by value, so what do I get in the function? Copied pointer that points to the same place/value?

function name(char *arg);
...
name(&cvar);

Can be analyzed the same as:

char *arg = &cvar;

arg is a pointer-to-char as per its declartion.

as cvar is itself already a pointer-to-char (from further above), then &cvar is a pointer-to-pointer-to-char.

So this assignment is also a type mismatch.

You might also look into

char carr [] = "hello world\n";

Here the string literal is taken as an array initializer rather than as a true string literal.

If this declaration is seen in the global context, static storage is not reserved for the literal, only for the array itself (which is initialized as expected).

If this declaration is seen in a local context, the literal may be stored somewhere, but we'll never see where that is because it would only be used internally to initialize carr (which will happen when flow of control reaches the initializer assignment), and the array carr is all that we can observe from within the language; We cannot observe the string literal's address as we can with char *cvar = "hi";, or something like printf("%s\n", "hi") ).