LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C typedef notation. (https://www.linuxquestions.org/questions/programming-9/c-typedef-notation-771051/)

corp1126 11-23-2009 01:49 PM

C typedef notation.
 
Hi all,

I'm working with some legacy C code and am unsure about some notation I'm seeing. I essentially have the situation below,

Code:

void func_A(stuff)
{
    //Stuff

    func_B(x,1L);

    //More stuff
}

void func_B(int *n,long x)
{
    //Stuff
}

The first function calls the second and provides as one of the arguments a long int that is, in this case, not a variable but is always 1. But instead of giving it simply "1" or "(long) 1" as I might have expected, it gives it "1L". My question is whether this is valid notation or not? Is it some sort of short hand for casting a int as a long int? Or is this nonsense?

Thanks very much!

MBybee 11-23-2009 02:05 PM

It's a short hand to a cast, it means that the 1 passed won't be the default for a constant, which is the shortest form possible. 1 would be more likely a short or int, and not a long.

I'm not a big fan of passing a hardcoded constant like that, but to each their own, I suppose.
http://www.falvotech.com/content/pub...d-enumerations
http://people.msoe.edu/tritt/cpplang.html#suffixes

johnsfine 11-23-2009 03:29 PM

Quote:

Originally Posted by corp1126 (Post 3767106)
The first function calls the second and provides as one of the arguments a long int that is, in this case, not a variable but is always 1. But instead of giving it simply "1" or "(long) 1" as I might have expected, it gives it "1L". My question is whether this is valid notation or not?

It is valid.

Quote:

Is it some sort of short hand for casting a int as a long int?
No. It is the syntax for a long int constant.

1 is an int. If the expected data type were predeclared before the call, then I think the compiler would cast it to long.

(long)1 casts an int 1 to long.

1L is a long constant. It is not an int constant cast to long.

The difference between (long)1 and 1L is pretty subtle. Optimized code and maybe even unoptimized code should be the same. The result should certainly be the same. Depending on the predeclaration of the called function, even 1 might give the same answer.

For contrast consider (long)5000000000 vs. 5000000000L
5000000000 is an int that happens to equal 705032704 (on most common architectures), so (long)5000000000 is a long that equals 705032704. While 5000000000L is a long that, on X86_64 and other architectures with 64 bit long, equals 5000000000.

Since it is legacy code, it doesn't seem likely it was written for an architecture with 32 bit ints and 64 bit longs. X86 has 32 bit longs. Could it be from an architecture with 16 bit ints? Most times I've seen code like that it was written by someone lacking any clear understanding of when you might want a long vs. an int and getting away with bad mixtures because they're the same size on X86. So you might need to be careful of that.

corp1126 11-23-2009 04:36 PM

Quote:

Originally Posted by johnsfine (Post 3767226)
It is valid.



No. It is the syntax for a long int constant.

1 is an int. If the expected data type were predeclared before the call, then I think the compiler would cast it to long.

(long)1 casts an int 1 to long.

1L is a long constant. It is not an int constant cast to long.

The difference between (long)1 and 1L is pretty subtle. Optimized code and maybe even unoptimized code should be the same. The result should certainly be the same. Depending on the predeclaration of the called function, even 1 might give the same answer.

For contrast consider (long)5000000000 vs. 5000000000L
5000000000 is an int that happens to equal 705032704 (on most common architectures), so (long)5000000000 is a long that equals 705032704. While 5000000000L is a long that, on X86_64 and other architectures with 64 bit long, equals 5000000000.

Since it is legacy code, it doesn't seem likely it was written for an architecture with 32 bit ints and 64 bit longs. X86 has 32 bit longs. Could it be from an architecture with 16 bit ints? Most times I've seen code like that it was written by someone lacking any clear understanding of when you might want a long vs. an int and getting away with bad mixtures because they're the same size on X86. So you might need to be careful of that.

Thanks to both of you for your answers.

This code is probably early 90s and I'm not sure what that means in terms of the machines it was designed for. The reason I was suspicious of it was the mix of usages, sometimes just 1 is passed and sometimes 1L. From the context a long is probably better. Hence I think if I correct all the 1s to 1Ls then I should be OK? I doubt this is causing any of the bugs I'm chasing but it's good to rule it out (and learn something).


P.s. If you're interested,

The function in question is a wrapper for an MPI call that collects the maximum value of a variable over all the processors. In some cases it is dealing with an array and giving the maximum values of each element (stored in an array the same size as the original) and in other cases it is just a single integer (often the "status" variable, which gets the fail/success value of a function call). The long value in question tells the function how many elements there are. I don't see any problem with using a hard-coded constant in this context but since we want a flexible function (that might have to work on old systems I guess) it makes sense to keep it general. Hence the need for a long.

Also hence the debugging pain, parallel debugging's not good!

Dan04 11-23-2009 05:59 PM

Quote:

Originally Posted by corp1126 (Post 3767287)
This code is probably early 90s and I'm not sure what that means in terms of the machines it was designed for.

Take a look at the pointer variables. On 16-bit PCs, there were two types of pointers: "near" pointers were restricted to a 64K memory segment and "far" pointers could point anywhere. If you see vestiges of this distinction (such as the "p" vs. "lp" naming convention), then it was designed for a 16-bit system. Otherwise, it was probably designed for a 32-bit system.

In either case, "long" was probably 32 bits: 64-bit integers were uncommon then.

MBybee 11-24-2009 08:53 AM

Quote:

Originally Posted by johnsfine (Post 3767226)
It is valid.

No. It is the syntax for a long int constant.

1 is an int. If the expected data type were predeclared before the call, then I think the compiler would cast it to long.

(long)1 casts an int 1 to long.

1L is a long constant. It is not an int constant cast to long.

The difference between (long)1 and 1L is pretty subtle. Optimized code and maybe even unoptimized code should be the same. The result should certainly be the same. Depending on the predeclaration of the called function, even 1 might give the same answer.

For contrast consider (long)5000000000 vs. 5000000000L
5000000000 is an int that happens to equal 705032704 (on most common architectures), so (long)5000000000 is a long that equals 705032704. While 5000000000L is a long that, on X86_64 and other architectures with 64 bit long, equals 5000000000.

Thanks for the refinement - I hadn't really appreciated the difference due to the fact that I've only touched on an object like this once before. I appreciate the correction, and have noted it :)

smeezekitty 11-24-2009 10:40 AM

Quote:

The first function calls the second and provides as one of the arguments a long int that is, in this case, not a variable but is always 1. But instead of giving it simply "1" or "(long) 1" as I might have expected, it gives it "1L". My question is whether this is valid notation or not? Is it some sort of short hand for casting a int as a long int? Or is this nonsense?

Thanks very much!
Basically the same as ((long)1).
It works for f for float and u for unsigned too.
Quote:


1 is an int. If the expected data type were predeclared before the call, then I think the compiler would cast it to long.

(long)1 casts an int 1 to long.

1L is a long constant. It is not an int constant cast to long.

The difference between (long)1 and 1L is pretty subtle. Optimized code and maybe even unoptimized code should be the same. The result should certainly be the same. Depending on the predeclaration of the called function, even 1 might give the same answer.

For contrast consider (long)5000000000 vs. 5000000000L
5000000000 is an int that happens to equal 705032704 (on most common architectures), so (long)5000000000 is a long that equals 705032704. While 5000000000L is a long that, on X86_64 and other architectures with 64 bit long, equals 5000000000.

Since it is legacy code, it doesn't seem likely it was written for an architecture with 32 bit ints and 64 bit longs. X86 has 32 bit longs. Could it be from an architecture with 16 bit ints? Most times I've seen code like that it was written by someone lacking any clear understanding of when you might want a long vs. an int and getting away with bad mixtures because they're the same size on X86. So you might need to be careful of that.
I do not think this is true for 16bit little endian machines.
Quote:

Take a look at the pointer variables. On 16-bit PCs, there were two types of pointers: "near" pointers were restricted to a 64K memory segment and "far" pointers could point anywhere.
anywhere within the first megabyte
Quote:

If you see vestiges of this distinction (such as the "p" vs. "lp" naming convention), then it was designed for a 16-bit system. Otherwise, it was probably designed for a 32-bit system.

In either case, "long" was probably 32 bits: 64-bit integers were uncommon then.
Dont work on turbo C++


All times are GMT -5. The time now is 07:14 PM.