Ask coding questions

← Back to all posts
Destructuring in C
h
Pankak (49)

I was wondering if destructuring is possible in C. Here's an example in pseudocode of what I'm thinking of:

void func({
  int foo;
  int foo2;
}){

}

struct {
  int foo;
  int foo2;
} victim;

Not particularly necessary but I recall finding something about this or something similar, which I can't find now.

@Coder100 @xxpertHacker smert ppl halp

Comments
hotnewtop
Coder100 (18933)

misread

uh this seems like something that seems too pleasant to exist in C

Pankak (49)

@Coder100 okay yeah expected that

xxpertHacker (931)

By the power of God Undefined Behavior, I've figured it out:

https://repl.it/@xxpertHacker/destructing-in-C

Both of y'all @Coder100, @MocaCDeveloper dissing C like that, smh, in C, anything is possible.

Pankak (49)

@xxpertHacker wait dafuq that makes no sense

xxpertHacker (931)

@Pankak But it works, doesn't it?

xxpertHacker (931)

@Pankak Lmao, ofc it is, it's UB; I'm reusing the values that were still left on the stack to automatically fill x and y, but that is exactly how a destructuring operation would be compiled, just push some values to the stack, and use those as the variables, so at least it's performant. (btw, even -O1 will make this fail)

Btw, you probably heard that C# has destructuring, not C.

Pankak (49)

@xxpertHacker I see, so not practical in any sense though

xxpertHacker (931)

@Pankak Nope, not even slightly.

I tried smth like this:

{
    T temp {
        .x = 100,
        .y = 200,
    };
}
int x;
int y;

but they got filled with garbage, so, there's no way to do destructuring ¯\_(ツ)_/¯

Pankak (49)

@xxpertHacker wait only one way I could kinda think of it is with a function. You provide with the struct you want to destructure and the number of members, and using your ud behavior destructure it. Maybe also provide it with a callback with the function but this runs into the problem of the function only being able to destructure one struct and not being able to have other arguments (unless we use variadic args and keep the destructured struct last in the params, but still, limitations). Or if you're able to do something like this

// undefined behavior thing

foo(int x, int y);

UNLESS that works which would still limit it to 1 destructured struct but whatever

Probably easier to just do

foo(bar.1, bar.2)

xxpertHacker (931)

@Pankak Na, doesn't work with params, it has to initialize params from the stack directly for that UB to have worked.

Also, do you want to destructure multiple structs? That sounds weird.

Pankak (49)

@xxpertHacker yeah I have multiple victims

FlaminHotValdez (716)

@xxpertHacker U were dissing C too... hypocrite

xxpertHacker (931)

@FlaminHotValdez Lmao, I was dissing C's preprocessor, not the language itself.

Pankak (49)

@xxpertHacker no you were dissing macros, theres nothing wrong with the preprocessor. I agree macros are evil beings which shall not be touched, but its kind of like that one neighbor who snipes dogs when they poop in his yard and is a pure evil life form which you shall never be associated with, but eventually you're gonna have to ask him to borrow his sniper to assassinate your ex girlfriend

xxpertHacker (931)

@Pankak Lmao, just don't get the gf and you're safe all around.
Better yet, move out of the neighborhood, so you don't have to deal with either, your gf, or the evil neighbor. (equivalent to not using C at all)

There are legitimate uses for the preprocessor: handling different versions of the language and checking compiler flags.

Btw, what's so bad about sniping dogs?

FlaminHotValdez (716)

@xxpertHacker lol. how many languages have you dissed? it's at least 1

Pankak (49)

@xxpertHacker

Btw, what's so bad about sniping dogs?

Sniping dogs is animal abuse, use something less painful like a landmine, bomb, 10 petawatt laser, or use concentrated plutonium vapor to provide the creature with a less agonizing death, it's a win-win

xxpertHacker (931)

@FlaminHotValdez Hmmm... a whole lot :)
I've dissed the following:

  • HTML (in favor of XHTML)
  • XHTML (in favor of Lisp syntax)
  • C
  • C++
  • JavaScript
  • TypeScript
  • Python
  • CSS
  • Node.js (doesn't count)
  • Java
  • C#
  • Lisp
  • Go (I think?)
  • PHP
  • English (the human language)
  • ...(Click to view ∞ more)
xxpertHacker (931)

@Pankak

Sniping dogs is animal abuse, use something less painful like a landmine, bomb, 10 petawatt laser, or use concentrated plutonium vapor to provide the creature with a less agonizing death, it's a win-win

You have to offset the price with the value, a bullet isn't too expensive, but getting an explosive is expensive.
It also takes time for the black-market smuggler to ship a landmine.
In contrast, the dog isn't worth much, so the dog doesn't pay for itself.

Also, what if I want to eat the animal afterward? Its corpse needs to stay intact.

FlaminHotValdez (716)

@xxpertHacker lol, remember when you said C++ was useless and I proved u wrong

xxpertHacker (931)

@FlaminHotValdez No? When? Can you link this discussion?

FlaminHotValdez (716)

@xxpertHacker in the why does no one use java? i told u they used c++ in competitive programming

FlaminHotValdez (716)

@xxpertHacker lmao yea, but the thing is they only allow C, C++, Java, Python, basically the biggest langs in USACO, Codeforces, all the big contests. among those C++ has the fastest execution time and is therefore favored.

Pankak (49)

@xxpertHacker

tell me you haven't lost braincells reading his answers, I sometimes question why I'm even on a website full of 11 year olds

xxpertHacker (931)

@Pankak

tell me you haven't lost braincells reading his answers,

I've lost just about all of 'em reading Ryan's answers, most are not even remotely helpful.
The only thing that's worse than the answer, is the fact that people mark them as "correct."
Some of those suggestions aren't even languages.

I sometimes question why I'm even on a website full of 11 year olds

I'm usually on GitHub, or ... anywhere else, I just use Repl to run code. (a desktop PC would be 10x better)
That, and I check out whenever someone pings me for C/C++.

(for lulz; reference to Ryan)

Please mark this as correct by clicking the checkmark on the left side

Pankak (49)

@xxpertHacker

I'm usually on GitHub

The only thing that's worse than people marking them as "correct" is being a programmer and spending most of your time on GitHub. You're sure hella addicted to version control.

xxpertHacker (931)

I got the ping 30mins late.

Na, this is isn't possible in C, it's possible in C++ and Rust though.

You can have block scopes that return values:

int foo() {
    int x = ({
        int x = 100;
        x + 1;
    });

    return x; // 101
}

you can declare structs with values directly:

typedef struct {
    int a;
    int b;
} T;

T test = {
    .a = 100,
    .b = 1
};

But no, this isn't possible.

Rust is a cool language that you might be interested in: https://repl.it/@xxpertHacker/destructuring

Also, I don't use C. The thought of using C is distasteful to me.

MocaCDeveloper (713)

@xxpertHacker

Hmm, this is what I said to I STG if he marks you correct this is rigged -_-

Jk lmao but ya I told him that and he kept telling me I don't understand his question.

xxpertHacker (931)

@MocaCDeveloper I agreed with him though, you kept focusing on the syntax error, lmao, btw, updated my answer.

Btw, even the elections were rigged, so it's okay.

Pankak (49)

@MocaCDeveloper I would've marked you as correct had you not complained about my pseudocode for 20 minutes and would've marked xxpertHacker's as correct had he not dissed macros :(

But I'll give both of you an upvote since you're so thirsty to have a random 64 bit floating point number increment

xxpertHacker (931)

@Pankak I didn't diss macros because I wanted a number incrementation on my cycles, lol, I dissed macros because I don't like 'em.
Since it is expected to only ever hold an integer, why would anyone implement a cycle counter using a floating-point number?
It would be better implemented as a u16, instead of an f64. Coder100 still has 50k cycles to go before a u16 would be insufficient, since it caps at 0x10000, or 64k.

Pankak (49)

@xxpertHacker Was assuming repl used js backend or does it use Go?

xxpertHacker (931)

@Pankak They use TypeScript and Go for their backend.

MocaCDeveloper (713)

@Pankak

Lmao I was simply stating that C could not possible do that due to its strictly typed syntax.

xxpertHacker (931)

@MocaCDeveloper

... its strictly typed syntax

I've never heard that phrasing before, "strictly-typed syntax"

MocaCDeveloper (713)

@xxpertHacker

Strictly type syntax? I'm surprised you've never heard that.
Strictly typed as in like type declarations, very strong on syntax etc..

xxpertHacker (931)

@MocaCDeveloper Is there such thing as "weakly-typed syntax"!?

xxpertHacker (931)

@MocaCDeveloper Searching up "strictly type syntax" is only giving me strongly/staticially typed programming languages instead.

MocaCDeveloper (713)

@xxpertHacker

Yes head yourself over to Python lmao

xxpertHacker (931)

@MocaCDeveloper Python has a stricter syntax than C, wdym?
Python forces spacing, C forces brackets.

MocaCDeveloper (713)

@xxpertHacker

Strictly typed as in declaring variables types, function return types etc.

Pankak (49)

@MocaCDeveloper lol wat, "strictly typed syntax" isn't a thing, I guess "strict syntax" would make sense but whats the "typed" in this?

Pankak (49)

@MocaCDeveloper

Strictly typed as in declaring variables types, function return types etc.

Thats called language design? I think what you mean is strong and weak typing, not "strictly typed syntax" or whatever you blobbered

xxpertHacker (931)

@MocaCDeveloper

Strictly typed as in declaring variables types, function return types etc.

I'm even more lost as to wtf what you're trying to explain.
Are you suggesting that C is "strongly" typed?

xxpertHacker (931)

@Pankak That's what I'm saying, "typed" makes no sense here, I've never heard it once.

Pankak (49)

@xxpertHacker reminds me of someone who said variables take too much memory and slows down your computer

xxpertHacker (931)

@Pankak Lmao, there are a finite number of registers that variables can be stored in, so they're wrong.

Pankak (49)

@xxpertHacker when did I mention they were my friend? Also I know they're wrong

xxpertHacker (931)

@Pankak

reminds me of someone...

Opps, didn't double-check.

MocaCDeveloper (713)

Um no I do not believe you can do this. That would be invalid syntax.

Pankak (49)

@MocaCDeveloper just an example in pseudocode, I am wondering if the concept is possible in C though

MocaCDeveloper (713)

@JBYT27

Invalid syntax, line 1:
Uncaught '{' in function declaration.

Lmao ya pretty much xD

MocaCDeveloper (713)

@Pankak

Pseudocode often uses structural conventions of a normal programming language

What you gave above in your example is invalid syntax code for the C language.

Pankak (49)

@MocaCDeveloper You aren't understanding my question, I am asking if the concept of destructuring is possible in C, and gave an example of what it would possibly look like in C so responders can understand my question. I was not intending it to be valid C code because I'm essentially asking if it even exists. Not precisely as provided syntax, but just the concept in general.

MocaCDeveloper (713)

@Pankak

No it's not possible. The most you can do is use the #define macro to give your own names to built-in keywords in the language...

Example:

#define I int
#define o {
#define c }
#define r return

i main() o
  r 0;
c
Pankak (49)

@MocaCDeveloper thats not what I'm asking though...

also you did macros backwards facepalm

MocaCDeveloper (713)

@Pankak

Ya I know oops xD
I actually can't believe I did that and I literally write C everyday xDD oof

Pankak (49)

@MocaCDeveloper writes C everyday, writes macros backwards somehow

MocaCDeveloper (713)

@Pankak

I got no sleep last night I am tired don't judge me :c

xxpertHacker (931)

@MocaCDeveloper Macros are bad, just don't use them at all.

MocaCDeveloper (713)

@xxpertHacker

They are useful when it comes to short instructions you want to compile. Then they are useful because then you can just use macros to implement actual C code wherever you want, without needing actual functions..ya know?(I am talking about macro functions, macro constants are useless)

xxpertHacker (931)

@MocaCDeveloper Both are bad.

My casual code:

(conditon ? macrofoo : macrobar)(...args);

Doesn't work with macros, only with functions >:|

MocaCDeveloper (713)

@xxpertHacker

I like using them when it comes to simple things like printing errors etc lol.
It's real simple and doesn't cause any slower compilation which is pretty efficient speaking of the fact that you will use them quite a bit.

xxpertHacker (931)

@MocaCDeveloper

  • The do slow down compilation
  • they may lead to binary thrashing
  • printing errors is something that ought to be a function
  • they prevent LLVM/compiler optimizations, as many compilers optimize on a function-by-function basis before inlining.
  • Functions are more reusable; ex: can be used as callbacks on top of direct calling.

Macros are only needed by the lazy.

MocaCDeveloper (713)

@xxpertHacker

I bought a book about C and quote

Macros are not seen by the compiler, instead the macro is seen as pure C code later referenced upon using the macro itself.

So how does it slow down compilation?
Also, how would it lead to binary thrashing? Just curious, didn't know that could occurr.

And I don't use LLVM. It all depends on the type of compiler you use and if you want to optimize your code or not. If you do, then yes of course macros will be a problem.
And while functions are more reusable, macros are often time replacements of functions. Why create a function that does something simple when you can write a macro the the compiler will use to place actual C code and not even recognize it as a macro OR a function?

xxpertHacker (931)

@MocaCDeveloper
It inlines the code... do you know what binary thrashing is?

Storing / opening / running a massive binary can help cause it, and inlining everything certainly encourages code bloat.

Think about it, every function call from main, could be inlined into main, do this recursively, and you end up with a massive block of executable code within a single function, oh, but those aren't even functions, they're macros, so this does happen.

So how does it slow down compilation?

Macros inline their code, forcing the frontend to parse+lex more code, and causing the backend to analyze the same structure multiple times over, whereas, if it were a single function, it could parse, lex, and optimize it easily, and only do it once, as opposed to macros which effect every single call site.

And I don't use LLVM. It all depends on the type of compiler you use and if you want to optimize your code or not.

Have you never used the Clang compiler at all?
This applies to any compiler regardless, compilers compile code, whether or not they optimize it doesn't matter, it has to be compiled somehow.
If you want to optimize it, you just add more separate locations that each, individually, need to be optimized now.

Pankak (49)

@xxpertHacker macros are useful, just don't overuse them, for example:

#define RED_COLOR 3

...

printcolor(RED_COLOR);

In that case it improves readability. There are also other uses.

Also it does slow down compilation, but by such a small amount it is not even an issue at all. The pre processing and parsing is optimized, and they are the fastest part of compilation.

Also just look at any open source C project, such as the linux kernel and Apache HTTP server to name a few. They have thousands if not ten thousands of macros.

Macros inline their code, forcing the frontend to parse+lex more code, and causing the backend to analyze the same structure multiple times over, whereas, if it were a single function, it could parse, lex, and optimize it easily, and only do it once, as opposed to macros which effect every single call site.

You're going on a rampage here and not speaking clear English, but I know what you're getting act. Probably just another poor victim of overusing macros then realizing and starting a hate relationship with it.

xxpertHacker (931)

@Pankak
Lmao, okay, sure, I use macros, but I don't use C.

#define RED_COLOR 3

...

printcolor(RED_COLOR);

could easily be:

unsigned const RED_COLOR = 3;

...

printcolor(RED_COLOR);

could it not?

Maybe you want to add some new colors, it'll be even easier to not use macros:

unsigned const
    RED_COLOR = 3,
    BLUE_COLOR = 2,
    GREEN_COLOR = 1;
...

printcolor(RED_COLOR);

But, even then I would call that poor code since it ought to be an enum in the first place:

enum Color {
    Green = 1,
    Blue,
    Red
}

... and not speaking clear English

What did I say that wasn't clear? Can you elaborate?

MocaCDeveloper (713)

@xxpertHacker

Well see now..macros primarily are what you just put down.
And as @Pankak has said, macros may cause slower compilation time but its not even noticeable since after all in the end you're primarily just getting what you put above out of a macro.

As my book says:

Macros can be seen as C code stored for later use that the compiler won't touch or even notice until used, and upon usage of the macro the compiler still will not comprehend it to be a macro but to be pure C code.

Which supports @Pankak statement of which the slowness won't even be able to be recognized since the compilation stage is the most important part.
Yes, it may take a bit more instructions for the lexer and the parser, but it own't take all that much.

Some people prefer macros, some prefer the way you do it.
I use macros because quote:

Macros are a essential part of the C programming language. They store C code for later usage, when needed, which makes it efficient when you don't really need a function.

xxpertHacker (931)

@MocaCDeveloper

Macros are a essential part of the C programming language. They store C code for later usage, when needed, which makes it efficient when you don't really need a function.

That's some bs that probably came from a 3-decade old C book, where'd you get that quote?
C isn't a bare metal language anymore, therefore that quote is no-longer relevant today.

...the compilation stage is the most important part.

Lmao, that was my argument :/
It's not the fact that it's a macro, it's the fact that it duplicates the code.
Also, iirc, the preprocessor may cause UB.
Everything about the C preprocessor seems lazy.

FAQ:
Does C have a proper module system?
No, it drops text into place via the preprocessor.

Does C have constants?
It doesn't matter because people like to drop magic literals into place via the preprocessor. Lazy.

Does C have enums?
It doesn't matter because people would rather just name a macro with an underscore, and drop it in via the preprocessor.

When dropping in a file via preprocessor, will it only be imported once?
No, it will be imported N times over, you need more macros to make it not do that.

...

The language could've been better, but the preprocessor was the easy way out.

MocaCDeveloper (713)

@xxpertHacker

@xxpertHacker

Well I mean that is not wrong. Macros are an essential part of the C programming language.

Many, MANY developers and many MANY well known projects/software use macros in there C code.
Now, when I said 'the compilation stage is the most important part' I was contradicting your argument since macros don't cause all that much harm to compilation.

And while the preprocessor may seem lazy, it is, as you said:

the easy way out

You can't expect too much from a low level language that of C. If you expect a bit more head over to C++.

There are a few advantages of the preprocessor however:
1. Enables easier readability
2. Enables easier modification
3. More transportable between different machine architecture

The C preprocessor is a macro processor that is used automatically by the C compiler to transform your program before actual compilation.

The preprocessor does all the "dirty" work for macros. Which then again supports my claim:

Macros are an efficient part of the C language

Now, it could've been better..yes. I agree. But in all honesty there is not much you can expect from C which is why C++ came around.

xxpertHacker (931)

@MocaCDeveloper
C++ came around because Bjarne knew liked objects and thought that C should have 'em too.

I dislike OOP, so a strongly-typed C with templates/generics is all that I want. HolyC is strongly-typed but doesn't offer generics, so I use C++ ¯\_(ツ)_/¯. Also, C++ has a "proper" module system, and I know that LLVM has had support for it for some time.

  1. Enables easier readability
  2. Enables easier modification
  3. More transportable between different machine architecture

Very few arguments have made me think, "wtf," but yours is definitely one of them. You have no backing for your claims whatsoever, and it's really detrimental to what you're trying to argue.

  1. Enables easier readability

How? Readability for who?
Is this macro,

#define MACRO(num, str) {\ 
            printf("%d", num);\ 
            printf(" is");\ 
            printf(" %s number", str);\ 
            printf("\n");

is more readable than a function?

void function(
    int const num,
    char const * const str
) {
    printf("%d", num);
    printf(" is");
    printf(" %s number", str);
    printf("\n");
}

Like, I understand, if semi-colons are readable enough already, why not use ; \, it's not every day that someone defends that.

  1. Enables easier modification

This is where I stopped and called this a "wtf argument."
What are you even defending?

I just searched up C macros:
https://www.geeksforgeeks.org/multiline-macros-in-c
I get an article that casually says how they can help cause bugs.

  1. More transportable between different machine architecture

This is "wtf: take 2." There is no explanation whatsoever and you bring no data that suggests anything of the sort.

C compilers ship a few separate parts already, a preprocessor, a frontend (parser+lexer), and a backend (compiler/codegen), wouldn't it be easier to remove a part, and ship less?

If they can already port all of that above ^, then why couldn't someone just update the compiler? C compilers are usually written in C.

Now, it could've been better..yes. I agree. But in all honestly, there is not much you can expect from C which is why C++ came around.

C could legitimately have modules that would have no runtime over head.

C has the concept of "scope," you know what scope is? An imaginary boundary that limits variable access.
it has no runtime overhead, in fact, more scope allows better optimizations.

void foo() {
    {
        int const x = call();

        bar(x, x);
    }

    {
        int const x = call();

        qux(x, x);
    }
}

How many registers would have to be allocated for this function call? Two variables would mean two registers, right?

Nope, any mediocre compiler would reuse the same register, as the first variable is probably not usable later, as it is no longer in scope.

Scope changes visibility, that is all that is needed for a module :/


Oh yeah, and that "strict syntax" is complete bs.

What it should look like:

if (foo) {
    bar;
} else {
    quux;
}

What it's allowed to look like:

int foo(), bar(), quux();

(((main)))() {
    if (foo)(bar);else(quux);

    float inf = 0x1.0p0 / 0x0.0p0,
	nan = -(inf / inf);
{ { { { { { inf; }}}}}}

    do; while (
		nan
	==nan);

    return ({ main; });

	printf(&nan);
}

foo() {}

bar() {}

Btw:

Pankak (49)

@xxpertHacker you're comparing a macro to a function, they aren't the same thing and should not be compared. The real question is understanding when to use macros and when not to. I agree that macros are evil, but they have legitimate uses, and avoiding them altogether is just naive

JBloves27 (1905)
  1. do not ping people like that, they might be busy and its not polite
  2. what do you mean? confused
  3. have a good day
Pankak (49)

@JBYT27

  1. they won't mind :D
  2. I gave an example in pseudocode:
void func({
  int foo;
  int foo2;
}){

}

struct {
  int foo;
  int foo2;
} victim;

If we pass in victim to func, the first param will restructure victim so we can access foo and foo2 as individual variables. I don't expect such a low-level language to have this but this will remove the necessity to use global struct types.

  1. you too
JBloves27 (1905)

ok... still confused and thanks! @Pankak

MocaCDeveloper (713)

@Pankak

The code you're giving is error prone and is invalid syntax.
If you want to pass the victim struct, declare it before declaring the func functions, then do:

void func(struct victim vic)

Here is what you're wanting to do:

struct {
  int foo,
  int foo2
} victim;

void func(struct victim vic) {

}
Pankak (49)

@MocaCDeveloper -_-

I'm not trying to write perfect C code here, hence why it's called pseudocode. Additionally, that was my example based on my imagination of what destructuring might look like in C, which is supposed to enhance the understandability of my question. If you need a clarification on what destructuring means:

vvv this is pseudocode and not a real language

foo = {
  param = 1
  param2 = 2
}

function test ({
  param
  param2
}){
 print param
 print param2
}

test(foo);

// should print 1 and 2
MocaCDeveloper (713)

@Pankak

I told you, no it is not possible but the closest you can get to pseudocode is the example I gave you

MocaCDeveloper (713)

@JBYT27

No I was just saying it's literally impossible.

xxpertHacker (931)

@Pankak

they won't mind :D

I mind, I wasn't even on my Repl tab when you pinged me >:|
You want to destructure your victims, hmm, kinda suspicious.