Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
| Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
10-16-2012, 07:35 AM
|
#1
|
|
Member
Registered: Dec 2011
Location: London, UK
Distribution: Slackware64 14
Posts: 94
Rep: 
|
Learning 64bit C
Hi all,
I am wanting to learn C, but am thinking that it may be worth learning to write 64bit C from the ground up. However, all of the tutorials that I have come across are aimed at writing 32bit code.
Any materials that are available would be appreciated. Also, any input or pointers on how to do so
Regards,
Jack
|
|
|
|
10-16-2012, 07:39 AM
|
#2
|
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,047
|
There is no such thing as "32-bit C" and "64-bit C".
|
|
|
|
10-16-2012, 07:40 AM
|
#3
|
|
Member
Registered: Dec 2011
Location: London, UK
Distribution: Slackware64 14
Posts: 94
Original Poster
Rep: 
|
Quote:
Originally Posted by NevemTeve
There is no such thing as "32-bit C" and "64-bit C".
|
Ok, well programs written in C that are targeted towards the 64bit architecture. Sorry, should have been clearer.
|
|
|
|
10-16-2012, 08:19 AM
|
#4
|
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,047
|
There are same common problems that arise when you migrate from 32-bit to 64-bit (like assuming that sizeof(int)=sizeof(pointer), but if you start to learn on a 64-bit platform (or better, if you compile your programs in both modes), you won't have these problems.
example:
Code:
$ cat >siz.c <<DONE
/* siz.c */
#include <stdio.h>
int main (void)
{
printf ("sizeof (char)=%d\n"
"sizeof (short)=%d\n"
"sizeof (int)=%d\n"
"sizeof (long)=%d\n"
"sizeof (long long)=%d\n"
"sizeof (void *)=%d\n"
, (int)sizeof (char)
, (int)sizeof (short)
, (int)sizeof (int)
, (int)sizeof (long)
, (int)sizeof (long long)
, (int)sizeof (void *)
);
return 0;
}
DONE
$ gcc -m32 -o siz32 siz.c && ./siz32
sizeof (char)=1
sizeof (short)=2
sizeof (int)=4
sizeof (long)=4
sizeof (long long)=8
sizeof (void *)=4
$ gcc -m64 -o siz64 siz.c && ./siz64
sizeof (char)=1
sizeof (short)=2
sizeof (int)=4
sizeof (long)=8
sizeof (long long)=8
sizeof (void *)=8
|
|
|
1 members found this post helpful.
|
10-16-2012, 08:22 AM
|
#5
|
|
Senior Member
Registered: Dec 2007
Distribution: Mepis, Centos
Posts: 4,680
|
Programs in C ought to be written portably, so they work despite differences between 32-bit and 64-bit.
For most programs, that isn't even an issue. It tends to take pretty advanced programming to even create a situation in which the natural way to code something is non portable and extra effort is then required to make it portable.
For example, the single most common non portable usage is assuming that an int and a pointer are the same size (which is true in x86 and other typical 32-bit architectures but false in x86_64 and some other 64-bit architectures). A beginner probably never sees a situation in which there would be any reason to make such an assumption, so avoiding such assumptions doesn't take any effort at all.
In more abstract programming, you often have a situation in which a parameter is passed from code that knows its type to ultimately reach other code that knows its type, but in between goes through code that doesn't know the type. You can do that correctly with a union. But it is enough easier via casts that many programmers have accidentally inserted non portable assumptions about size via such casts.
|
|
|
3 members found this post helpful.
|
10-16-2012, 08:49 AM
|
#6
|
|
Senior Member
Registered: Dec 2007
Distribution: Mepis, Centos
Posts: 4,680
|
If you expect to care about performance, there is one programming habit I would start early because of its benefits in x86_64 architecture (it does no harm in x86 or other architectures):
Invent an index type and use a typedef to make it the same as unsigned int
Code:
typedef unsigned int index_t;
Then, whenever you have a variable that counts or indexes elements of an array, or a variable that loops through moderate size non negative values, use that type instead of using (what most people use) int.
Code:
for (index_t n= ...)
instead of
When doing this (using unsigned int instead of size_t) you are limiting your program to 4 billion elements in any one array. But when you think about that, you realize it is not much of a limit. A 64-bit program can use far more than 4GB of memory without approaching 4G elements in one array. It may even have more than 4G Bytes in one array of structs without close to 4G structs in that array.
By using a typedef, you make it easy to change the program later, when problem size has grown so much that 4G elements per array is a real limit.
By using unsigned int now, you get better code now.
In 32-bit, int and unsigned int and size_t all perform exactly the same in the binary code, so in the common case where any one of them is correct, there is no performance difference either.
But in x86_64, in the common loop and index situations where any one of those types would give the right results, unsigned int tends to cause the compiler to generate smaller binary instructions (compared to either int or size_t) creating lots of situations in which the interaction between the L1 cache and the instruction pre fetch runs more smoothly, creating code that runs slightly faster (despite the actual operations of unsigned int being the same nominal speed as those with size_t). ( int often needs extra instructions for sign extend where a non asm programmer wouldn't expect such a difference).
I expect most other experts would argue in favor of going directly to size_t, so that you don't need to guess at the time you write the program whether someone will use it later with arrays over 4G elements. Whether you agree with them or with me, part of the suggestion is the same: In 32-bit C programming you see a lot of indexes that are declared as int. In 64-bit C programming, int usually works as an index, but using it is a very bad habit to get into.
Last edited by johnsfine; 10-16-2012 at 08:58 AM.
|
|
|
2 members found this post helpful.
|
10-16-2012, 10:12 AM
|
#7
|
|
Senior Member
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 4,554
|
I would strongly echo JohnsFine's advice here, because when you define the string size_t (or whatever it may be), you are defining ... in one easily-found and easily-changed place ... a word that has meaning. In other words, size_t foo; is saying both to the computer (who really doesn't care) and to the programmer (who does!!) that "foo is a size_t."
It's very important when writing code to make your intentions clear, not just to the computer but also to the person who's picking-up after you following "that very unfortunate incident involving the bread truck." (Your funeral is next Friday...) Simple tricks like the one he suggests not only make the code more portable, but also more meaningful. In some cases and with some (other) languages they can also enable the compiler to detect the kind of "niggling mistakes" that are so often the consequence of an un-noticed tpyo. (The hair-follicles that you save will be your own, and the day will come, at least for all you gentlemen out there, when that is very important.)
|
|
|
1 members found this post helpful.
|
10-16-2012, 11:16 AM
|
#8
|
|
Senior Member
Registered: Dec 2007
Distribution: Mepis, Centos
Posts: 4,680
|
Quote:
Originally Posted by sundialsvcs
when you define the string size_t (or whatever it may be), you are defining ...
|
Just to be clear, when I mentioned size_t, I meant the standard one described here
http://en.wikipedia.org/wiki/C_data_...fference_types
When I used the example of index_t I was suggesting defining your own type name, for situations where a careless or beginner programmer would use int without thinking and where a careful programmer writing portable code might correctly use (the standard) size_t. In those situations, I prefer defining and using my own type name for the reasons described above.
In x86_64, size_t is a 64 bit unsigned integer, which can make it slower in many situations where a 32 bit unsigned integer is good enough.
Last edited by johnsfine; 10-16-2012 at 11:20 AM.
|
|
|
1 members found this post helpful.
|
10-16-2012, 11:33 AM
|
#9
|
|
Member
Registered: Dec 2011
Location: London, UK
Distribution: Slackware64 14
Posts: 94
Original Poster
Rep: 
|
Thanks for the responses. I think it'll be easier to abide by these pieces of advice if I get in habit of following them right from the beginning.
Thanks again.
|
|
|
|
10-16-2012, 11:37 AM
|
#10
|
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,047
|
If I might risk a guess, in actual programs you cannot win considerable CPU-time via using 32 bit long variables as indices instead of 64 bit longs -- especially when they reside in registers.
|
|
|
|
10-17-2012, 09:48 AM
|
#11
|
|
Member
Registered: Aug 2012
Location: Chiang Mai, Thailand
Distribution: Kubuntu 12.10 x86_64
Posts: 190
Rep:
|
Okay, here is a little bit different output when you compile this code on both 32-bit and 64-bit OS:
Code:
/* Successfully compiled with: gcc -std=c99 -Wall test.c */
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t current_time = time(NULL);
for (;;)
{
printf("Fast time: %s\n", ctime(¤t_time));
current_time += 9999; // 999 or 9999 is up to you.
}
return 0;
}
After sometime, you should see the difference that the time on the 32-bit OS has been reset from 2038 to 1901.
While on the 64-bit OS, It keeps on going.
|
|
|
1 members found this post helpful.
|
10-17-2012, 10:11 AM
|
#12
|
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,047
|
Good point: never assume that time_t is equal to int. (In Unix, it is equal to long, but that may change without warning.)
Other types, like off_t an ino_t, depend on compiler options:
-m32, without LargeFileSupport: 32 bit
-m32, with LargeFileSupport: 64 bit
-m64: 64 bit
|
|
|
|
10-17-2012, 09:53 PM
|
#13
|
|
Member
Registered: Aug 2012
Location: Chiang Mai, Thailand
Distribution: Kubuntu 12.10 x86_64
Posts: 190
Rep:
|
Quote:
Originally Posted by suttiwit
Okay, here is a little bit different output when you compile this code on both 32-bit and 64-bit OS:
Code:
/* Successfully compiled with: gcc -std=c99 -Wall test.c */
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t current_time = time(NULL);
for (;;)
{
printf("Fast time: %s\n", ctime(¤t_time));
current_time += 9999; // 999 or 9999 is up to you.
}
return 0;
}
After sometime, you should see the difference that the time on the 32-bit OS has been reset from 2038 to 1901.
While on the 64-bit OS, It keeps on going.
|
If forgot to add that:
For 32-bit systems though, there is a little hack on this but it does not work with ctime();
Code:
/* Successfully compiled with: gcc -std=c99 -Wall test.c */
#include <stdio.h>
#include <time.h>
int main(void)
{
unsigned long long current_time = time(NULL);
for (;;)
{
printf("Fast time: %llu\n", current_time);
current_time += 9999; // 999 or 9999 is up to you.
}
return 0;
}
Time will not reset on 2038. But still: ctime() does not want to convert.
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 05:25 AM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|