The '*' is not a part of the type declaration (suprisingly), so

The '*' is not a part of the type declaration (suprisingly), so
void *ptr;
And that's because of
void *a, *b, *c;

Other urls found in this thread:

stackoverflow.blog/2017/06/15/developers-use-spaces-make-money-use-tabs/
twitter.com/AnonBabble

((void (*)(void))void)();

It feels like it should be a part of the type declaration though. It feels like I should be making a "void pointer" data type, not a "void" type but then saying "actually I want a pointer that'll dereference into that type".

>void *ptr

What is this? 1975?

You shouldn't declare multiple variables on one line regardless

>it's X but it should have been Y
C has some awful design flaws, that we've been forced to live with since the 70s.

I'm not a huge fan of multiple declarations, because
1) variables should be initialised on declaration to avoid potential mistakes
2) with C99 and newer, variables should be declared first when needed (minimal scope declarations)

char a, *b, **c

The type of a is char.
The type of *b is char.
The type of **c is char.

How many compilers don't actually support C99 at this point?

It's not so much about compiler support, but more about what legacy projects still use. If you write Linux LKMs for example, they will spit out warnings if you don't declare your variables C89-style.

As for actual compilers, MSVC doesn't support anything newer than C89. But it does support C++ though.

void
*
ptr
;

>MUH FEELINGS
Well its a good thing we are working in a logic language and not a feeligns language.
You are declaring a void. Deal with it.

Its part of the standard. There is nothing wrong with it.
can you explain why you have an issue with it?

If void* isn't the type, then explain to me why this isn't valid:

void a;

fuck you

None.

Because using pointers in the current year is retarded and only old farts who still think they are relevant will use a programming language that allows this sort of garbage.

typedef void* void_ptr;


:^)

>I am afraid of memory management.

typedef void * pointer_to_an_unspecified_region_of_memory_t;

>reinventing the wheel
Of course your time is not important, you're either a NEET or an old fucker on verge of death.

void *a is generating a memory address without bullshitting around with type limitations

void a is obviously retarded. If this were python or something without types then it would be normal I guess. Why would you ever want a type of "void" if you arnt working with memory addresses?

>void *a is generating a memory address without bullshitting around with type limitations
Really? No limitations, you say. Then explain to me why this is illegal then:

void* a = "hello, world\n";


>Why would you ever want a type of "void" if you arnt working with memory addresses?
My point is that the pointer-type (aka void*) is clearly the type, not void.

gcc doesn't even give me any warnings for that

My guess would be that "Hello, world\n" is a string made up of an array of memory addresses which would be equilivant to char a[14];. It wouldnt fit into a single memory address.

Well, that's why you shouldn't rely on compilers to identify (potential) undefined behaviour.

void* a = "hello, world\n";
char* b = a;
b[5] = 'c'; // this is UB

Why is that undefined?

That's not the problem. The problem is that "hello, world\n" is a string literal. String literals are by definition const memory, meaning that any decent compiler will put them into read-only section of memory. This assignment casts away the const modifier, and can potentially lead to undefined behaviour (see )

See b points to a string literal.

If *void is the type, then explain to me why this is valid:

void func(){/*some code*/}

Yea, I saw that example.
void* a = "hello, world\n";
is basically a buffer overflow, is it not?
would something like the following work? Im not compiling shit for a Sup Forums debate
void *a[14] = "hello, world\n";

Each character takes one memory address. That is the reason your example is invalid. You cant fit a sentence into the space of a single letter.

First one, since indirection is not part of the type, but rather part of the relationship between the type and the variable.

It would have to be
void a[14] = "hello, world\n";
and you can't declare an array of voids

Void isn't a type. It indicates the absence of a variable.

That shouldn't be any more undefined than casting a char * to a void *.

>is basically a buffer overflow, is it not?
No

>Each character takes one memory address.
No

>That is the reason your example is invalid. You cant fit a sentence into the space of a single letter.
char* points only to the address of the first byte. You're confusing pointers and arrays. String literals are not char arrays, they are memory references to read-only memory.

printf("%zu %zu %zu\n", sizeof(void*), sizeof(int*), sizeof(long long int*)); // these should all be the same size

The string literal "hello, world\n", which a points to, is located in read-only memory. Trying to modify that region of memory is undefined behavior.

No, it wouldn't be a buffer overflow, since a string on the right side of an initialization statement is creating a string literal. In C, a void may point to a string literal without any casting.

You're missing the point. The undefined behaviour is GCC implicitly casting away the const modifier, without even providing a warning.

Well yeah, modifying a string literal is illegal obviously. I meant using a string literal to initialize a void pointer.

>void a[14] = "hello, world\n";
This doesn't compile.

>and you can't declare an array of voids

I'm pretty sure C doesn't require string literals to be declared const, it just states that modifying them may invoke UB. It's C++ that complains if you initialize a pointer-to-non-const-char with a string literal.

>I meant using a string literal to initialize a void pointer.
The string literal is just a memory reference (aka an address) to where the actual content is stored.

>and you can't declare an array of voids
Well then that seems like the issue.
You should be using "char a" instead anyway.

But you asked why you cant fit a string into a char and I explained that.

While on this subject, seeing your example I am reminded of something that was done like char *a[14] = {'h','e','l','l','o',',',' ','w','o','r','l','d','\n'};

Its been a long time since I have programed anything and its eluding me, what is the difference in this and the way you put it

>As for actual compilers, MSVC doesn't support anything newer than C89
What? For real??

That's because void isn't a type.

>I'm pretty sure C doesn't require string literals to be declared const, it just states that modifying them may invoke UB.
I'm not entirely sure, I thought that even just casting away the const was UB. But maybe I'm mistaken.

What the fuck is *void

Yes, for real.

This is also undefined behaviour:
char* a = "hello, world\n";
a[5] = 'c';


>what is the difference in this and the way you put it
Well, first of all your example is invalid. You have declared a as an array of char pointers, but you're initialising it as an array of chars.

Secondly, pointers and arrays are not the same thing. In C, arrays are contiguous memory areas. Pointers are memory references. HOWEVER, and this is important, a pointer MAY point to a contiguous memory area (aka it may reference an array).

A string literal isn't JUST an address, it's an expression that A) constructs* a string in potentially non-writable memory and B) returns a pointer to the first character. It's basically a compile-time equivalent of a constructor (in the C++ sense).

*I think C implementations are allowed to do string interning if the same string literal is used multiple times, since you're required to treat them as immutable anyways

But in any case, a char * can be assigned to a void * variable without issues, so logically using a string literal to initialize a void pointer should be fine.

>so undefined behaviour:
Been drinking and forgot to edit the astrict out.
I was focusing on everything after the = sign.

In your example you are declaring it as if it was a string, but what I was remembering is declaring the array using = { "H", 'e', ...}; with the brackets and everything.

In practice it supports a lot of C99 features, simply because those features are part of C++ (and MSVC is primarily a C++ compiler). But it doesn't make any attempt to meet any official C standards beyond C89. You might get away with using C99 constructs is MSVC, but that's purely incidental.

Option 1, but with only one space.

>he doesnt use tab in the middle of declaration

You can initialize on declaration with the single-line style though.

user, you cannot use a scripting language like Javascript, Python, or Lua, unless you understand what a pointer is. Otherwise you'll be terribly confused by the behavior of objects, lists, dicts, etc.

stackoverflow.blog/2017/06/15/developers-use-spaces-make-money-use-tabs/

Do whatever the hell you want but at least be consistent about it.

Higher-level languages honestly confuse me more than C because I never know whether it's copying the object or just passing a reference

It's almost always a reference because that's the only behavior that makes sense from a performance standpoint.

For aggregate types*

I've always been fine declaring multiple things on one line if they were effectively the same sort of thing in the code (not just the type).

For example, if I have am declaring both row major order arrays, as well as just another general array for something else, I might do this.
double *a, *b, *c; // Matrices
double *x; // Other array


I do agree that declaring all of those one line would be bad practice, though.

void* ptr;

because it makes sense and all that old documentation that shows otherwise is wrong.

Tabs are also better than an arbitrary number of whitespaces you fuck.

>Tabs are also better than an arbitrary number of whitespaces you fuck.

I'd wager that 90%+ of developers who use spaces agree that tabs for indenting and spaces for alignment is objectively the best way to apply white space to your code. However, close to 100% of competent developers who program in a professional environment also realize that it only takes one fuckup to start pressing tab for alignment that fucks up the entire system. Forcing spaces on everyone fixes this. Similarly, 100% of competent developers are too busy making actually programming, and just have a checkbox marked in there IDE/Editor that says "Expand tab into spaces", and don't worry about trivial shit like this.

void *ptr
This is the best way to define pointers. If you pretend that the * is actually part of the name, you can use it just like any other variable name.

void* ptr

Be the change you want to see in C.

>tabs for indenting and spaces for alignment
Nobody agrees that mixing tabs and spaces is a good idea. Fuck off.

Other points are accurate though

I don't like the idea of one character having a different width than every other character

int *p

* is the dereference operator. You declare a variable p that dereferences to an integer.
(dereference) p is an int

> There are people in the world who advocate putting the star with the type, but who also advocate the "p" hungarian notation prefix.
Really makes you think.

but it doesn't user, it's a single character. You can tell your text editor to replace it with whatever you want, including how wide it is. I like 3 space width, but that's just how my text editor is rendering it.

I actually render tabs like this, so I know they're tabs and not whitespaces.

>Nobody agrees that mixing tabs and spaces is a good idea. Fuck off.

You might be retarded if you use tabs for alignment. What do you do if you want dont want to align your text in some factor of the tabwidth? What will you do when someone opens your file and displays tabs a different width, and suddenly all your alignment is off? There are literally zero good reasons to ever use tabs for alignment.

im retarded user forgive me, sublime also has a cool way to show the difference between tabs and spaces.

Which is why no one should ever use tabs under any circumstances ever.

/thread.

the multiple declarations are just a symptom of the issue, not the core of it.

people who write void* ptr; and similar are trying to make a language into something it is not, which just makes them look stupid.

Multiple declarations are a useful and intuitive way to group logically-related variables together, not a "symptom."

If you're going to use tabs, you might as well be writing code in Microsoft Word. Since the width of tabs can vary between environments, they're basically incompatible with a column count limit. And many editors treat a tab as a single character, which will mess up your column counts anyways.

It's not a Hungarian prefix, since "tr" isn't meaningful on its own. It's literally just naming what the variable is, that has nothing to do with Hungarian.

Not all editors have that feature.

The first in C and C++, the second in C#

This

>Not all editors have that feature.
editing tab width is like the _most basic_ of text editor features.

wait, so if you just had
void *a, b, c;
b and c wouldn't be pointers?

Yes. But the worst part is in
void* a, b, c;
b and c won't be pointers as well.

the second one. It's a void pointer not a ptr pointer.

oh god I've been doing it all wrong, I need to go.

Strictly speaking, that's not legal C at all. But on some old compilers you end up with b and c as chars.

In C, you declare variables the way you will invoke them. That guides how you place the stars, brackets, etc.

>In C, you declare variables the way you will invoke them
There's no standard requiring this. Unless you follow hungarian notation, this makes no sense to me.

It's the way C's variable declaration syntax was designed and intended.

There isn't a syntax, man. You choose to do it that way or you don't. And if it's the way K&R says it should be, that doesn't mean it's set in stone.

It's a mnemonic that makes sense.

2 is the LOGICAL way, but it's not how it works. 1 simply to not shoot yourself in the foot in the future.

I don't follow. when you declare an int or a char or a byte, you don't do anything to the variable name. Why would you do anything differently for pointers?

Actually thank you, you helped me realize it doesn't matter what way it's done. I like my way but who cares?

auto &thing = another_thing;

You declare a pointer like this:
int *x;
and you deref it like this:
*x
Therefore the declaration exactly mirrors the way the variable is accessed.

The same rule applies to typedefs:
typedef int **type_t[12][3];
type_t x
you get an int back out of that using
**x[0][0]

>you deref it like this
exactly you deref it with *. Which is a separate symbol than declaring a pointer. They really should have used carets or some other symbol to indicate a dereference over a pointer.

They chose not to because declarations in C mirror the way you access the variable. It's a choice that's designed into the language. It is the same symbol on purpose.

b points to the "hello world\n" in the data section. In this case it has nothing to do with the fact that a is a void*. If you wrote void* a = strdup("hello, world\n"); instead, then it would be well defined

I think this part is well-defined:
void *a = "hello world"
Dereferencing a (after casting it) and reading from it are also well-defined. But trying to write to the destination of a is undefined. Could be a segfault, could modify just that string, could modify _anywhere_ that uses the string literal "hello world" if it gets deduplicated (or just everywhere in the same translation unit.) I have observed multiple different behaviors on different compilers/platforms.

Thats because you are thinking about it wrong.
* gets the value of the representation of the pointer.
So by doing int *ptr, the thing "*ptr" is an int, "ptr" is a pointer to an int

that's what I just said ()

>he's been making first-year CS mistakes all along
bruh

>2017
>C instead of asm