• Hey, guest user. Hope you're enjoying NeoGAF! Have you considered registering for an account? Come join us and add your take to the daily discourse.

Programming |OT| C is better than C++! No, C++ is better than C

Bowlie

Banned
Hi, everyone! Just wanna say that I've been lurking in this thread for quite some time, and now that I'm planning to learn C# (I'm comfortable with C, Python and Java) I'm super glad there's a ton of resourceful sites in the OP for me.

I hope that in the future if I encounter some problem or doubt, I could come here and share it with y'all.
 

kingslunk

Member
That's not really going to work for him. He reads the number 4.2, and the value returned is less than 4.2 Ceil is just going to give you 5. If you mean ceil(4.2*100), then it might be represented as 4.19xxxx or 4.20xxxx, so you'll be calling ceil(419.xxxx) or ceil(420.xxxx) and if it's the latter then ceiling might give you 421.

(int)(x * 100.0 + 0.5) sounds best to me.

Edit: I'm stupid. Best solution is (int)roundf(x * 100.0f)

not static_cast<int>?
:p
 

Trident

Loaded With Aspartame
Any tips on how to account for that? I went back and checked and the error IS happening after the float gets converted to an int (I even ran it step-by-step through gde and somehow just missed that step happening. :l) . How can I change the code to get an accurate result?

Take the input as a string and convert it to an integer, ignoring the decimal point. No math needed.
 

Koren

Member
You go character by character. You ignore non-numbers, like the . and the in . ( &#865;° &#860;&#662; &#865;°)
^_^

So 4.20 is ten times 4.2? Interesting maths... I love the whole discussion, why use a bad idea when you can find an even worse one?

How about displaying 4.2 as a captcha that give access to a porn website? It has already been used why great success ^_^
 
Code:
int main(void) {
    char last_initial;
    printf("What is your name? : ");
    string name = GetString();
    printf("%c", name[0]);
    for(int i= 0; i < strlen(name); i++){
        if(name[i] == ' ') {
            last_initial = name[i+1];
            printf("%c", last_initial);
        }
    }
    printf("\n");
}

So I'm going over some of my stuff from last semester and trying to improve on them. What's a better way to do this? Ultimately, you type in your name and it spits out your initials. Is there a better way to handle this? Having 3 printf statements seems like a bit much.
 
You got a Bsc in computer science. Just look for jobs asking for a junior programmer or something like that. If it asks for 3+ years of experience? Still apply, most likely its not a hard demand.

What is important is that you find a place that has enough senior programmers to learn from. Dont take a job where you are the only programmer. During an interview, ask a lot of questions about training and personal growth and how they keep up to date and such. You dont want to end up at a place where they have been programming in Java 1.4 for the past 15 years.

1. Anything with associate in it, ie associate programmer, developer, software engineer etc. People sadly use these titles interchangeably.

2. In my experience no. Popular languages and technologies change all the time. Problem solving and good computer science fundamentals never do. A better thing to do is decide what kinds of problems you want to solve and look into jobs in those areas.

3. The biggest thing I've learned about side project stuff is it provides people a way to evaluate you that might not come across in an interview and it allows you to show passion for a specific domain that you might be trying to get paid for eventually. I personally think its better to work on something you care about and feel strongly about even if you are the only one working on it.



Yeah when I went to school it was a junior level course. They made it non required and I ended up not taking it but I briefly took the Coursera Stanford Compilers class last year. Low level stuff is really fascinating to me (even though I am not great at it) but in these days of people mostly writing web stuff fewer people seem to care.

Thanks for the advice guys, I got an email today to schedule an introductory interview, so I'm excited and nervous now. I'll probably spend the next few days studying and preparing. This is the big job I want and the minimum requirements are barebones, so I think I have a decent shot.

Even if I don't get the job I've been contacted by a few staffing companies interested in my resume. I've been spending my time working on learning C# by making a CRUD application and then later I plan to start learning Asp .net and making a CRUD application on there.
 

vypek

Member
Thanks for the advice guys, I got an email today to schedule an introductory interview, so I'm excited and nervous now. I'll probably spend the next few days studying and preparing. This is the big job I want and the minimum requirements are barebones, so I think I have a decent shot.

Even if I don't get the job I've been contacted by a few staffing companies interested in my resume. I've been spending my time working on learning C# by making a CRUD application and then later I plan to start learning Asp .net and making a CRUD application on there.

Good luck on your interview!
 

Koren

Member
Code:
int main(void) {
    char last_initial;
    printf("What is your name? : ");
    string name = GetString();
    printf("%c", name[0]);
    for(int i= 0; i < strlen(name); i++){
        if(name[i] == ' ') {
            last_initial = name[i+1];
            printf("%c", last_initial);
        }
    }
    printf("\n");
}

So I'm going over some of my stuff from last semester and trying to improve on them. What's a better way to do this? Ultimately, you type in your name and it spits out your initials. Is there a better way to handle this? Having 3 printf statements seems like a bit much.
I'd use a flag for this: initial position set (for the first character), raise it on space, drop it on non-space (and print the non-space). This way, you cope with leading and trailing spaces, double spaces, and spare a printf. Adding support for - is straightforward (just the test to change)

After that, it depends, for the loop, which version of C++ you use.

(assuming it's C++)

Basic solution (using .length, though, it's more logical for string strings, I'd say that strlen is for char* strings):
Code:
	bool isInitial = true;
	
	for(int i=0; i<name.length(); ++i) {
		if (name[i]==' ') {
			isInitial = true;
		} else if (isInitial) {
			isInitial = false;
			printf("%c", name[i]);
		}
	}
	printf("\n");

Sligthly better solution using a string iterator (you don't need 'auto', but it's shorter than specifying the complete iterator type):
Code:
	bool isInitial = true;
		
	for(auto ich=name.begin(); ich!=name.end(); ++ich) {
		if (*ich==' ') {
			isInitial = true;
		} else if (isInitial) {
			isInitial = false;
			printf("%c", *ich);
		}
	}
	printf("\n");

A probably far better solution, but only available to recent C++X11 compilers (gcc and clang at least) :
Code:
	bool isInitial = true;
	
	for(char& ch : name) {
		if (ch==' ') {
			isInitial = true;
		} else if (isInitial) {
			isInitial = false;
			printf("%c", ch);
		}		
	}
	printf("\n");

I think the new 'for' syntax that allow a string to be iterated over the characters is nice...

But ultimately, it depends on the style of code you want...

If you want something small, you can always 1line the loop:
Code:
	bool f=true;
	for(char& c:name)f=(c==' '?true:f?printf("%c",c),false:false);
	printf("\n");

;)
 
Code:
int main(void) {
    char last_initial;
    printf("What is your name? : ");
    string name = GetString();
    printf("%c", name[0]);
    for(int i= 0; i < strlen(name); i++){
        if(name[i] == ' ') {
            last_initial = name[i+1];
            printf("%c", last_initial);
        }
    }
    printf("\n");
}

So I'm going over some of my stuff from last semester and trying to improve on them. What's a better way to do this? Ultimately, you type in your name and it spits out your initials. Is there a better way to handle this? Having 3 printf statements seems like a bit much.

You can do this easily with sscanf, provided the user only enters two words (which your original code assumes):

Code:
int main(void) {
    char first[256] = {0};
    char last[256] = {0};
    printf("What is your name? : ");
    string name = GetString();
    sscanf(name, "%s %s", first, last);
    printf("%c%c\n", first[0], last[0]);
}

It's vulnerable to a buffer overflow though, so don't use it if you're worried about that. We can also remove the call to GetString with scanf:

Code:
int main(void) {
    char first[256] = {0};
    char last[256] = {0};
    printf("What is your name? : ");
    scanf("%s %s", first, last);
    printf("%c%c\n", first[0], last[0]);
}
 
It's vulnerable to a buffer overflow though, so don't use it if you're worried about that. We can also remove the call to GetString with scanf:

Code:
int main(void) {
    char first[256] = {0};
    char last[256] = {0};
    printf("What is your name? : ");
    scanf("%s %s", first, last);
    printf("%c%c\n", first[0], last[0]);
}

You can specify the field width for scanf to prevent buffer overruns, can't you? (reserving 1 char for the null).

Code:
scanf("%255s %255s", first, last);
 
I don't know enough C for this...is that bitshifted value on the right being cast to a type that's a union of a float and uint32? And then 496 is subtracted?

Rewrite it like this:

Code:
union u {
    float v;
    uint32_t r;
};

u foo {(int)x};
return (foo.r + 0x1fffff>>21) - 496;

So you're close, but you've just said what it is, not why
 
I have the weirdest Windows issue I've seen yet. My CMD scripts won't recognize certain environment variables I created in earlier scripts! Here's what I've tried for debugging so far:

- Every time I make a change I close and reopen the cmd prompt to refresh the cmd's environment variables copy
- This happens if the variables are in HKLM or HKCU
- Both variables have 16 characters (thought it might be a 16 character limit?), but longer and shorter variables will display fine (from both HKLM and HKCU)
- Happens with setlocal on and off
- Happens if it's either .cmd or .bat
- Happens if I delete and recreate the keys manually
- cmd "set" does not display them (bad parent copy)

Seriously, I'm at a loss here.
 
I have the weirdest Windows issue I've seen yet. My CMD scripts won't recognize certain environment variables I created in earlier scripts! Here's what I've tried for debugging so far:

- Every time I make a change I close and reopen the cmd prompt to refresh the cmd's environment variables copy
- This happens if the variables are in HKLM or HKCU
- Both variables have 16 characters (thought it might be a 16 character limit?), but longer and shorter variables will display fine (from both HKLM and HKCU)
- Happens with setlocal on and off
- Happens if it's either .cmd or .bat
- Happens if I delete and recreate the keys manually
- cmd "set" does not display them (bad parent copy)

Seriously, I'm at a loss here.

You mention environment variables but then talk about registry keys. So I'm not sure what you're talking about. Are you dealing with environment variables or registry keys? The SET command has nothing to do with HKLM and HKCU
 
Combo, but it's just environment variables I'm after. Some read using %var%, some read var's registry key, some write to var by writing to the Environment key in the registry.

EDIT: Yes, set just modifies the local process' copy of the environment variables right?
 
Combo, but it's just environment variables I'm after. Some read using %var%, some read var's registry key, some write to var by writing to the Environment key in the registry.

EDIT: Yes, set just modifies the local process' copy of the environment variables right?

Yes. I'm also still not following though. Like you say this:

This happens if the variables are in HKLM or HKCU
This sentnece doesn't make sense to me, because how can an environment variable be in HKLM? They're totally unrelated things.
 
Yes. I'm also still not following though. Like you say this:


This sentnece doesn't make sense to me, because how can an environment variable be in HKLM? They're totally unrelated things.

OK, I'm googling now in case I find the answer before you respond but are HKCU/Environment and HKLM/SYSTEM/CurrentControlSet/Control/Session Manager/Environment not somewhat tied? A mixture of both their variables are spit out when you use set.

EDIT: Yeah, one's for the current user. One's for the machine (all users). Both are saved after logoffs and restarts.
 
OK, I'm googling now in case I find the answer before you respond but are HKCU/Environment and HKLM/SYSTEM/CurrentControlSet/Control/Session Manager/Environment not somewhat tied? A mixture of both their variables are spit out when you use set.

Maybe, but if they are it's not documented and you're not supposed to rely on that.

Make a batch file with 1 line:

SET TESTVAR=FOO

When I run this I get this output:

Code:
C:\Users\Me>set TESTVAR
Environment variable TESTVAR not defined

C:\Users\Me>foo

C:\Users\Me>SET TESTVAR=FOO

C:\Users\Me>set TESTVAR
TESTVAR=FOO

Is this not what you get?
 
Maybe, but if they are it's not documented and you're not supposed to rely on that.

Make a batch file with 1 line:

SET TESTVAR=FOO

When I run this I get this output:

Code:
C:UsersMe>set TESTVAR
Environment variable TESTVAR not defined

C:UsersMe>foo

C:UsersMe>SET TESTVAR=FOO

C:UsersMe>set TESTVAR
TESTVAR=FOO

Is this not what you get?
Yep
 
By "Yep" I assume you mean that your output doesn't match that. What if you just run the commands without a batch file:

Code:
C:> SET TESTVAR=FOO
C:> SET TESTVAR
FOO

Is that what you get?
Oh goodness, I'm sorry; I responded too quickly. Yep meant "my output does match that." I got the same result as you.
 
Oh goodness, I'm sorry; I responded too quickly. Yep meant "my output does match that." I got the same result as you.

If that's the case then maybe you more clearly explain the problem? That shows that the environment variable is persisting after you run the batch script, so I don't quite follow what's happening and what you expect to happen.

You originally said the environment variables you set in one script aren't being recognized in later scripts. Are those later scripts run from the same instance of cmd, or from a different instance of cmd?
 
If that's the case then maybe you more clearly explain the problem? That shows that the environment variable is persisting after you run the batch script, so I don't quite follow what's happening and what you expect to happen.

You originally said the environment variables you set in one script aren't being recognized in later scripts. Are those later scripts run from the same instance of cmd, or from a different instance of cmd?

Ok, yeah. Sorry, let's try again.

I have a program that, among other things, runs a set of scripts. These scripts are spawned from the main process. In them, if I have environmental variables I want to use in later scripts I use the "reg add ..." command and write them to HKLM/.../Environment. Several of these spawned scripts are able to read from HKLM/../Environment or %...% to get the environment variables.

One of my scripts writes to the RunOnce key in HKLM before I restart the system. When the computer restarts, a script tries to read some of these environmental variables (stored in the HKLM/.../Environment key) but returns empty values. Scripts that run afterwards are no longer able to read from these variables, just write to them if I force a write. This includes after I've logged in to the system.
 
Ok, yeah. Sorry, let's try again.

I have a program that, among other things, runs a set of scripts. These scripts are spawned from the main process. In them, if I have environmental variables I want to use in later scripts I use the "reg add ..." command and write them to HKLM/.../Environment. Several of these spawned scripts are able to read from HKLM/../Environment or %...% to get the environment variables.

One of my scripts writes to the RunOnce key in HKLM before I restart the system. When the computer restarts, a script tries to read some of these environmental variables (stored in the HKLM/.../Environment key) but returns empty values. Scripts that run afterwards are no longer able to read from these variables, just write to them if I force a write. This includes after I've logged in to the system.

Ok now I understand. Your main process, let's call it foo.exe, is running a script. Not sure what language you're using, but I'll assume either Python or c++. In the former case you're probably using subprocess.Popen and in the latter you're probably using ShellExecute or CreateProcess or system.

In all of these cases, Windows is spawning a new instance of cmd which is a child process of your foo.exe, the variables are being set in there, and the process is exiting. Variables are not propagated up to the parent process. It's not running the batch file inside foo.exe

You've got a few options.

1) instead of calling CreateProcess with "foo.bat" call it with "foo.bat && set". Redirect stdout in your call to CreateProcess and parse the output, manually setting each variable in your environment to the corresponding value shown in stdout.

This is a huge hack, but people really do this in production.

2) Don't run scripts in your program. Often it's easier to just write actual c++ or Python to do what you're doing than it is to write these scripts.
 

luoapp

Member
Rewrite it like this:

Code:
union u {
    float v;
    uint32_t r;
};

u foo {(int)x};
return (foo.r + 0x1fffff>>21) - 496;

So you're close, but you've just said what it is, not why

What do you think about bin_index then?
foo.r>>23 is floor(log2(x))+127," +0x1fffff" picks out some cases and makes them 1 bigger. ">>21" instead of ">>23" makes it based 16 instead of based 2. Also 127<<2 = 508, the offset from 496 is 8 now, which I have no idea why.

I mean this is the code snippet from malloc, it must have been optimized to the extreme.
 
What do you think about bin_index then?
foo.r>>23 is floor(log2(foo.r))+127," +0x1fffff" picks out some cases and makes them 1 bigger. ">>21" instead of ">>23" makes it based 16 instead of based 2. Also 127<<2 = 508, the offset from 496 is 8 now, which I have no idea why.

I mean this is the code snippet from malloc, it must have been optimized to the extreme.

Why the union though? Why didn't he just write (uint32_t)x (I know the answer, just thought it was an interesting thing to try to understand).

Also foo.r >> 21 would be log2(x), but operator precedence says this is (foo.r + 0x1FFFFF) >> 21. So we've really got [foo.r + 2^(n-1)-1] >> n. This has to be some kind of bit twiddling operation, but I don't know what.
 

Koren

Member
Also foo.r >> 21 would be log2(x), but operator precedence says this is (foo.r + 0x1FFFFF) >> 21. So we've really got [foo.r + 2^(n-1)-1] >> n. This has to be some kind of bit twiddling operation, but I don't know what.
I'm only half awake and on a phone waiting for a late train, but is't it just a way to ceil the value before taking the log?

This way, the less significant bit after the shift is increased unless all last 21 bits from mantissa are 0.

I've yet to read te source it's coming from, but I assume x is greater than 0?

Fun trick, in any case.
 

luoapp

Member
Why the union though? Why didn't he just write (uint32_t)x (I know the answer, just thought it was an interesting thing to try to understand).

Also foo.r >> 21 would be log2(x), but operator precedence says this is (foo.r + 0x1FFFFF) >> 21. So we've really got [foo.r + 2^(n-1)-1] >> n. This has to be some kind of bit twiddling operation, but I don't know what.

foo.r>>23 is log2(x), the code shifts 2 bits fewer, not sure if the real intention here is to save a multiplication operation ( x4).
 

Koren

Member
foo.r>>23 is log2(x), the code shifts 2 bits fewer, not sure if the real intention here is to save a multiplication operation ( x4).
I'm pretty sure it's not just that.

The result is ceil(11 + log_k(x)) where k = 2 ^ (1/4) or in rarer cases the integer just above.

It's difficult to get an exact formula because, if I'm not mistaken, it's a function really close to ceil(11+log_k(x)) but between two values of log2(x) the steps are linear and not logarothmics.

I think they needed a function close to ceil(11+log_k(x)) but don't mind the slight error. But they probably want the last two bits.

F(2) is 16, F(4) is 20, but i think they find useful that F(2.5) is 17, F(3) is 18 and F(3.5) is 19.

Is the function related to space provisionning for containers somehow? (still haven't read the source, sorry)
 

luoapp

Member
I'm pretty sure it's not just that.

The result is ceil(11 + log_k(x)) where k = 2 ^ (1/4) or in rarer cases the integer just above.

It's difficult to get an exact formula because, if I'm not mistaken, it's a function really close to ceil(11+log_k(x)) but between two values of log2(x) the steps are linear and not logarothmics.

I think they needed a function close to ceil(11+log_k(x)) but don't mind the slight error. But they probably want the last two bits.

F(2) is 16, F(4) is 20, but i think they find useful that F(2.5) is 17, F(3) is 18 and F(3.5) is 19.

Is the function related to space provisionning for containers somehow? (still haven't read the source, sorry)

It's part of the code from some implementation of malloc. x is size_t type.

foo.r>>23 is foo.v >> 23, which is IEEE 754 single-precision binary floating-point, https://en.wikipedia.org/wiki/Singl...cision_binary_floating-point_format:_binary32
590px-Float_example.svg.png


The question is why >>21, +01ffff, -496 at the end, but I think that's implementation specific, i.e., I have no idea.
 
I think we can all agree this is a terrible hack.

I'm not convinced. We would need to know why these specific values are chosen first. It's obviously a hash of some sort (computing a bucket index) so there must be a reason why these values are desirable and some logical derivation.

Mostly i was posting it to illustrate the concept of casting an int to a float and then extracting the fields of the IEEE floating point representation, because I imagine many people never thought of that.

This is also a good illustration of why you should comment code :)
 

luoapp

Member
I'm not convinced. We would need to know why these specific values are chosen first. It's obviously a hash of some sort (computing a bucket index) so there must be a reason why these values are desirable and some logical derivation.

Mostly i was posting it to illustrate the concept of casting an int to a float and then extracting the fields of the IEEE floating point representation, because I imagine many people never thought of that.

This is also a good illustration of why you should comment code :)

It most likely not a hash, quote from http://git.musl-libc.org/cgit/musl/tree/src/malloc/DESIGN
Uses a freelist binned by chunk size, with a bitmap to optimize
searching for the smallest non-empty bin which can satisfy an
allocation. If no free chunks are available, it creates a new chunk of
the requested size and attempts to merge it with any existing free
chunk immediately below the newly created chunk.

It's an implementation of something like this http://ocw.mit.edu/courses/electric...amic-storage-allocation/MIT6_172F10_lec10.pdf
 

Somnid

Member
I'm not convinced. We would need to know why these specific values are chosen first. It's obviously a hash of some sort (computing a bucket index) so there must be a reason why these values are desirable and some logical derivation.

Mostly i was posting it to illustrate the concept of casting an int to a float and then extracting the fields of the IEEE floating point representation, because I imagine many people never thought of that.

This is also a good illustration of why you should comment code :)

Well it's a hack because it's not obvious what it does, clever as it may be. It might be fast, but it's not readable, for all anyone knows there's a bug here or it doesn't actually work as intended. How do you prove otherwise from looking at it?
 
It's part of the code from some implementation of malloc. x is size_t type.

foo.r>>23 is foo.v >> 23, which is IEEE 754 single-precision binary floating-point, https://en.wikipedia.org/wiki/Singl...cision_binary_floating-point_format:_binary32
590px-Float_example.svg.png


The question is why >>21, +01ffff, -496 at the end, but I think that's implementation specific, i.e., I have no idea.

Interestingly (x + 0x1FFFFF >> 21) is the same as (x + 2097151) / 2097152, which tells you how many 2097152 byte chunks you need to hold x bytes of data. But since x is an IEEE floating point number in this case, that doesn't really make sense.
 

luoapp

Member
Interestingly (x + 0x1FFFFF >> 21) is the same as (x + 2097151) / 2097152, which tells you how many 2097152 byte chunks you need to hold x bytes of data. But since x is an IEEE floating point number in this case, that doesn't really make sense.

That's why I asked if you checked bin_index(). bin_index_up( the one with 0x1fffff) only used once, so I guess this "+0x1fffff" trick is less important than >>21, and -496.
 

Koren

Member
I'm not convinced. We would need to know why these specific values are chosen first. It's obviously a hash of some sort (computing a bucket index)
A hash or a way t choose which chunk of memory you'll use depending on the data size? Usually, there's plently of small chunks, a bit less larger ones, and so on, the size of the chunks being usually something like 2^(3k) and the number of each size inverse proportionnal to the size.

Mostly i was posting it to illustrate the concept of casting an int to a float and then extracting the fields of the IEEE floating point representation, because I imagine many people never thought of that.
I must have spend far too much time doing low-level awfully crude things ^_^

Should you use C++ (probably not the case here), I'm wondering the pros and cons using the union trick and the reinterpret cast... The union trick work better with registers?

This is also a good illustration of why you should comment code :)
I suspect many of memory management pieces of code are directly linked to a paper on the matter. I wouldn't be surprised that the expression is explained somewhere, although it would have been easier if they had provided a link inside the code. Link can be broken, but I'm sometimes reluctant to detail all subtilities inside the code source. I just ship the code with documentation alongside it.

Well it's a hack because it's not obvious what it does, clever as it may be
I've thrown a glance at the source, and I'd say I can live with a strange formula if I at least know what the function is doing...

That's why I asked if you checked bin_index(). bin_index_up( the one with 0x1fffff) only used once, so I guess this "+0x1fffff" trick is less important than >>21, and -496.
That convinced me even more than it's a ceil (while bin_index truncates the value)

I mean,
x >> 21 transforms a (1+8+23) float into a (1+8+2) one by truncating it
(x+0x1fffff) >> 21 transforms a (1+8+23) float into a (1+8+2) one by ceiling it

And I don't think it's a coincidence that the formula keep exactly 2 digits from the fraction part of the floating number after a sum that can transform a truncation to 2 digits to a ceiling...

-496 is most probably -508 plus an offset.
 

JeTmAn81

Member
Rewrite it like this:

Code:
union u {
    float v;
    uint32_t r;
};

u foo {(int)x};
return (foo.r + 0x1fffff>>21) - 496;

So you're close, but you've just said what it is, not why

OK, so here's a log of my thought processes for dissecting this code. I haven't peeked below this post so this is what I came up with on my own.

Code:
union u {
    float v;
    uint32_t r;
};

What the heck is a union? Like I said, I don&#8217;t know that much C, so it&#8217;s off to Google.

A union is a special data type available in C that allows to store different data types in the same memory location. You can define a union with many members, but only one member can contain a value at any given time. Unions provide an efficient way of using the same memory location for multiple-purpose.

Ok, that makes sense. It&#8217;s like a struct but only one member at a time can have data. In this case, union u is going to have either a float value or an unsigned 32-bit integer value.

Code:
u foo {(int)x};

Here we&#8217;re declaring a variable called foo that has the type of our union u. The curly braces that follow indicate an inline initialization of the foo variable. The initialization process is provided a variable x that&#8217;s being cast to an int type. But, will this be assigned to the float member or the uint32_t member of the union?

When initializing a union, the initializer list must have only one member, which initializes the first member of the union unless a designated initializer is used (since C99).

Ok, so the variable x should be getting assigned to the first union member (this is the default when there&#8217;s no designator specified), which is the float variable v. But what about the cast in the initialization? Does casting it to an integer type affect this in any way?

It&#8217;s tempting to jump to the conclusion that casting this variable to an integer type will lead to it being assigned to the uint32 member rather than the float member, but I can&#8217;t find any documentation to support this and since the C11 specification costs actual monies to read ($60 for a PDF!!!), I can&#8217;t dive any further to discover how a compiler might treat this behavior. In this case, I must conclude that despite the cast, x is still being assigned to the float member v.

Code:
return (foo.r + 0x1fffff>>21) - 496;

Alright, we&#8217;re returning a value. Now, this is referencing the uint32 variable r which was not actually assigned, but since this is a union and the other member WAS assigned, then r will still be referring to actual data. So the integer value x should&#8217;ve been stored as the same value in the float variable v.

Code:
foo.r

Now we&#8217;re accessing our signed integer value, converted to a float, as an unsigned 32-bit integer. This can have unexpected results, especially if the number is negative. Converting a negative signed value to an unsigned value can lead to a very high positive value. But at this point I&#8217;m not sure what else to say is happening, other than adding the bit-shifted hex value and then subtracting 496.

Since the last operations are predicated on the value of an unknown variable x, I don&#8217;t know how to resolve this expression to an actual value. I definitely don't know why those particular values are being added and subtracted at the end.
 
OK, so here's a log of my thought processes for dissecting this code. I haven't peeked below this post so this is what I came up with on my own.

Code:
union u {
    float v;
    uint32_t r;
};

What the heck is a union? Like I said, I don’t know that much C, so it’s off to Google.



Ok, that makes sense. It’s like a struct but only one member at a time can have data. In this case, union u is going to have either a float value or an unsigned 32-bit integer value.

Code:
u foo {(int)x};

Here we’re declaring a variable called foo that has the type of our union u. The curly braces that follow indicate an inline initialization of the foo variable. The initialization process is provided a variable x that’s being cast to an int type. But, will this be assigned to the float member or the uint32_t member of the union?



Ok, so the variable x should be getting assigned to the first union member (this is the default when there’s no designator specified), which is the float variable v. But what about the cast in the initialization? Does casting it to an integer type affect this in any way?

It’s tempting to jump to the conclusion that casting this variable to an integer type will lead to it being assigned to the uint32 member rather than the float member, but I can’t find any documentation to support this and since the C11 specification costs actual monies to read ($60 for a PDF!!!), I can’t dive any further to discover how a compiler might treat this behavior. In this case, I must conclude that despite the cast, x is still being assigned to the float member v.

Code:
return (foo.r + 0x1fffff>>21) - 496;

Alright, we’re returning a value. Now, this is referencing the uint32 variable r which was not actually assigned, but since this is a union and the other member WAS assigned, then r will still be referring to actual data. So the integer value x should’ve been stored as the same value in the float variable v.

Code:
foo.r

Now we’re accessing our signed integer value, converted to a float, as an unsigned 32-bit integer. This can have unexpected results, especially if the number is negative. Converting a negative signed value to an unsigned value can lead to a very high positive value. But at this point I’m not sure what else to say is happening, other than adding the bit-shifted hex value and then subtracting 496.

Since the last operations are predicated on the value of an unknown variable x, I don’t know how to resolve this expression to an actual value. I definitely don't know why those particular values are being added and subtracted at the end.

Nice attempt, spot on until the part where he accesses foo.r.

Each field of a union shares the same storage bytes, so the size of a union is the size of the largest field plus alignment requirements. So the uint32 and the float literally share the same bytes. Initialization of the union casted the int to a float, so the bytes in the union are in IEEE single precision floating point representation. Accessing foo.r doesn't invoke a cast it's just treating the bytes differently, so the integral value of foo.r is meaningless, he's just doing this to manipulate the bits of the underlying IEEE floating point representation
 

Kieli

Member
Hi Gaf, I have a few questions as a beginning Java student:

When I try to change an object's field, is this the best way to do it?
this.property = this.getProperty() + parameter;

Also, what does the "static" keyword mean?
 

JeTmAn81

Member
Hi Gaf, I have a few questions as a beginning Java student:

When I try to change an object's field, is this the best way to do it?
this.property = this.getProperty() + parameter;

Also, what does the "static" keyword mean?

It depends on how you're treating the data. If the variables in the class are declared as public then you can just set or get them directly. Example:

Code:
class Foo 
{
   public int bar;
   public int upham;
}

Foo testobj = new Foo();
testobj.bar = 1;
testobj.upham = 2;

So you can just refer to them directly. But if they're declared as private you would need to declare getter and setter methods to manipulate them. Example:

Code:
class Foo 
{
   private int bar;
   private int upham;

   public int getBar()
   {
    return bar;
   }

   public void setBar(int newbar)
   {
    bar = newbar;
   }

   public int getUpham()
   {
    return upham;
   }

   public void setUpham(int newupham)
   {
    upham= newupham;
   }

}

Foo testobj = new Foo();
testobj.setBar(1);
testobj.setUpham(2);
System.out.println(testobj.getBar());
System.out.println(testobj.getUpham());

The static keyword means there's only one copy of that class or variable in existence at a time. So if you had a static class called Foo with the public members bar and upham, you could manipulate them at any time without having to declare an object of that class type such as testobj.

So instead of testobj.bar = 1, you could just do Foo.bar = 1. You refer to static member variables by the name of their containing class rather than an instantiated object.
 

Koren

Member
What's the easiest/best way of simulating a dice roll in C++?
Easiest and best won't go well together...

Result = rand() % 6;

Should fit most needs if you want an easy solution, but not all values have exactly the same probability, although in the worst case it's less than 0.0031% difference, and usually it's far far less than that.

Don't forget to seed with a

srand(time(NULL))

at the beginning of the code.


There's better random functions in recent C versions, like C++X11 but you may not need them.

And I won't relaunch the interesting debate on randomness ;)
 
Easiest and best won't go well together...

Result = rand() % 6;

Should fit most needs if you want an easy solution, but not all values have exactly the same probability, although in the worst case it's less than 0.0031% difference, and usually it's far far less than that.

Don't forget to seed with a

srand(time(NULL))

at the beginning of the code.


There's better random functions in recent C versions, like C++X11 but you may not need them.

And I won't relaunch the interesting debate on randomness ;)

That is interesting. Thanks.

If I'm using a multifile program, where exactly to I put the srand(time(NULL)) call? In the function responsible for dice rolls? In the file with implementation of the diceroll function? In the main file that calls on the diceroll function?
 

Ahnez

Member
That is interesting. Thanks.

If I'm using a multifile program, where exactly to I put the srand(time(NULL)) call? In the function responsible for dice rolls? In the file with implementation of the diceroll function? In the main file that calls on the diceroll function?

srand(x) redefines the seed, it must be called exactly once, and must be before the first call of the rand() function

Even if you put it on the dice roll file, you will have to create an unique function for it, and would have to call it in main. So Its better to just use it directly in main
 
srand(x) redefines the seed, it must be called exactly once, and must be before the first call of the rand() function

Even if you put it on the dice roll file, you will have to create an unique function for it, and would have to call it in main. So Its better to just use it directly in main

Got it. Thank you.
 
Top Bottom