473,382 Members | 1,736 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

pointers arithmetics

Please, help me with the pointers.

I've a base pointer, say it is a 0x06000000 and offsets from it to
registers (for example, #define REG1 0x04). I'm accessing to them in a
following way.

void *base = MEMBASE; /* 0x06000000 */
uint32_t val = 0;

val = ((uint32_t) *(base + REG1));
/* do something with val */
((uint32_t) *(base + REG1)) = val;

Is this code correct? I'm not sure because sizeof(void *) = 4, so (base + 4)
will be (base + 4 * (sizeof(void *))), that will point me to the incorrect
address. If it is true, then what will be the correct method?

Thanks in advance.

--
s/.../.gotovchits/g for email.
Sep 24 '07 #1
10 1498
Ivan Gotovchits said:
Please, help me with the pointers.

I've a base pointer, say it is a 0x06000000 and offsets from it to
registers (for example, #define REG1 0x04). I'm accessing to them in a
following way.

void *base = MEMBASE; /* 0x06000000 */
uint32_t val = 0;

val = ((uint32_t) *(base + REG1));
/* do something with val */
((uint32_t) *(base + REG1)) = val;

Is this code correct?
No, it's not. The code performs arithmetic on a void *, which is not legal
C. Furthermore, the result of a cast is not a modifiable lvalue, so it
cannot be the left operand of an assignment statement.
I'm not sure because sizeof(void *) = 4, so (base +
4) will be (base + 4 * (sizeof(void *))),
No, even if sizeof(void *) is 4, this is of no consequence to the
expression (base + 4). When you add N to P (where P is a pointer to some
object type), the result is a pointer value that points N objects past P,
where the size of the object is determined by computing the size of the
kind of object to which P points. Since one cannot take the size of such
an object when P is of type void *, the calculation is illegal.
that will point me to the
incorrect address. If it is true, then what will be the correct method?
Well, there isn't a "correct" method, but there are less incorrect methods!
That is, the C Standard doesn't make any guarantees about what will happen
when you do the following:

#define MEMBASE (void *)0x06000000UL

void *base = MEMBASE; /* 0x06000000 */
unsigned char *ucbase = base;
uint32_t val = 0;

val = *(uint32_t)(ucbase + REG1);
/* do something with val */
*(uint32_t)(base + REG1) = val;

but it does at least have a fighting chance of working as you expect on
*some* (but by no means all) implementations.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 24 '07 #2
>I've a base pointer, say it is a 0x06000000 and offsets from it to
>registers (for example, #define REG1 0x04). I'm accessing to them in a
following way.

void *base = MEMBASE; /* 0x06000000 */
uint32_t val = 0;

val = ((uint32_t) *(base + REG1));
Don't try to do math on void* pointers.
>/* do something with val */
((uint32_t) *(base + REG1)) = val;

Is this code correct? I'm not sure because sizeof(void *) = 4,
Could be true but it's not relevant to this situation.
>so (base + 4)
will be (base + 4 * (sizeof(void *))),
No, actually that's (base add 4 mul (sizeof(void *))), using
assembly-language operators instead of C operators. That's picking
nits, but it's an important distinction.

No, sizeof(void) is not defined, so (base + 4) might be anything.
>that will point me to the incorrect
address. If it is true, then what will be the correct method?
What units are you trying to use for REG1? Maybe your pointer
should be char *.

Sep 24 '07 #3
Gordon Burditt wrote:

Don't try to do math on void* pointers.
Yes, really it even fails to compile ...
What units are you trying to use for REG1? Maybe your pointer
should be char *.
I have a 32 bit register at the address base + 0x04 (i.e if base 0x06000000,
then reg will be found at the address 0x06000004)

--
s/.../.gotovchits/g for email.
Sep 24 '07 #4
Richard Heathfield wrote:
Ivan Gotovchits said:
>Please, help me with the pointers.

I've a base pointer, say it is a 0x06000000 and offsets from it to
registers (for example, #define REG1 0x04). I'm accessing to them in a
following way.

void *base = MEMBASE; /* 0x06000000 */
uint32_t val = 0;

val = ((uint32_t) *(base + REG1));
/* do something with val */
((uint32_t) *(base + REG1)) = val;

Is this code correct?

No, it's not. The code performs arithmetic on a void *, which is not legal
C. Furthermore, the result of a cast is not a modifiable lvalue, so it
cannot be the left operand of an assignment statement.
>I'm not sure because sizeof(void *) = 4, so (base +
4) will be (base + 4 * (sizeof(void *))),

No, even if sizeof(void *) is 4, this is of no consequence to the
expression (base + 4). When you add N to P (where P is a pointer to some
object type), the result is a pointer value that points N objects past P,
where the size of the object is determined by computing the size of the
kind of object to which P points. Since one cannot take the size of such
an object when P is of type void *, the calculation is illegal.
>that will point me to the
incorrect address. If it is true, then what will be the correct method?

Well, there isn't a "correct" method, but there are less incorrect
methods! That is, the C Standard doesn't make any guarantees about what
will happen when you do the following:

#define MEMBASE (void *)0x06000000UL

void *base = MEMBASE; /* 0x06000000 */
unsigned char *ucbase = base;
uint32_t val = 0;

val = *(uint32_t)(ucbase + REG1);
/* do something with val */
*(uint32_t)(base + REG1) = val;

but it does at least have a fighting chance of working as you expect on
*some* (but by no means all) implementations.
Thanks, I understand my errors.
So after all maybe it is better to use, something like this:

uint32_t *base = MEMBASE;
uint32_t *val = 0;

val = *(base + REG1/sizeof(uint32_t));

Will be this correct, if I know for sure that REG1 is divisable by 4?

--
s/.../.gotovchits/g for email.
Sep 24 '07 #5
Ivan Gotovchits said:

<snip>
So after all maybe it is better to use, something like this:

uint32_t *base = MEMBASE;
uint32_t *val = 0;

val = *(base + REG1/sizeof(uint32_t));
That's better, but better still (if you have control over REG1) would be to
define it as 1 rather than 4, allowing you to do this:

val = base[REG1];

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 24 '07 #6
Richard Heathfield wrote:
Ivan Gotovchits said:

<snip>
>So after all maybe it is better to use, something like this:

uint32_t *base = MEMBASE;
uint32_t *val = 0;

val = *(base + REG1/sizeof(uint32_t));

That's better, but better still (if you have control over REG1) would be
to define it as 1 rather than 4, allowing you to do this:

val = base[REG1];
Not really a full control. I have lots of them defined in the system header
file. So it is not a good idea to touch it.
--
s/.../.gotovchits/g for email.
Sep 24 '07 #7
Ivan Gotovchits wrote:
Please, help me with the pointers.

I've a base pointer, say it is a 0x06000000 and offsets from it to
registers (for example, #define REG1 0x04). I'm accessing to them in a
following way.

void *base = MEMBASE; /* 0x06000000 */
uint32_t val = 0;

val = ((uint32_t) *(base + REG1));
/* do something with val */
((uint32_t) *(base + REG1)) = val;

Is this code correct? I'm not sure because sizeof(void *) = 4, so (base + 4)
will be (base + 4 * (sizeof(void *))), that will point me to the incorrect
address. If it is true, then what will be the correct method?
As others have told you, void* arithmetic don't work.
I recommend that you start with writing two functions:

reg_set(REG_N, val);

val = reg_get(REG_N);
--
Tor <torust [at] online [dot] no>
Sep 24 '07 #8
Ivan Gotovchits wrote:
uint32_t *base = MEMBASE;
uint32_t *val = 0;

val = *(base + REG1/sizeof(uint32_t));
And I have another idea

uint32_t *base = MEMBASE;
uint32_t *val = 0;

val = *(((char *)base) + REG);

and it can be made a macros:
#define get_reg(REG) *(((char *)base) + REG)

Is it right and can it be simplified in any way?

--
s/.../.gotovchits/g for email.
Sep 25 '07 #9
Groovy hepcat Richard Heathfield was jivin' in comp.lang.c on Mon, 24
Sep 2007 10:12 pm. It's a cool scene! Dig it.
#define MEMBASE (void *)0x06000000UL

void *base = MEMBASE; /* 0x06000000 */
unsigned char *ucbase = base;
uint32_t val = 0;

val = *(uint32_t)(ucbase + REG1);
/* do something with val */
*(uint32_t)(base + REG1) = val;
^^^^
No doubt you meant ucbase, not base. Otherwise it has no chance of
working on any conforming implementation. (I don't know what it might
do on Jacob's compiler, however. <g,d&r>)

--
Dig the sig!

----------- Peter 'Shaggy' Haywood ------------
Ain't I'm a dawg!!
Sep 30 '07 #10
Peter 'Shaggy' Haywood said:
Groovy hepcat Richard Heathfield was jivin' in comp.lang.c on Mon, 24
Sep 2007 10:12 pm. It's a cool scene! Dig it.
>#define MEMBASE (void *)0x06000000UL

void *base = MEMBASE; /* 0x06000000 */
unsigned char *ucbase = base;
uint32_t val = 0;

val = *(uint32_t)(ucbase + REG1);
/* do something with val */
*(uint32_t)(base + REG1) = val;
^^^^
No doubt you meant ucbase, not base.
It doesn't seem to matter how carefully we check this stuff, does it?
There's *always* something.

Thank you, Peter. Better late than never. :-)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 30 '07 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Terence | last post by:
I need some clarification with pointer arithmetics on void *. Example 1: ======== char s; char *ptr = s; ptr += 1; // I assume ptr is increased by 1 byte, pointing to the 2nd element in the...
21
by: Milan Čermák | last post by:
Hi all, I'm about to write an arithmetics object library. It should contain classes like ShortInteger (for 32-bit longs), Double and Float as standard numeric type wrappers and LongInteger (really...
1
by: Jonas Ernst | last post by:
Hi, Can somebody give me some hints how to do a line interpolation without using floating point arithemtics? The function shall do a linear interpolation between 2 points (line interp?) and...
1
by: Rein Anders Apeland | last post by:
Hi all, We are developing a PoS application for Linux and are in need of a LGPL'ed og other 'free'-licensed library that can do exact decimal arithmetics for us. It should be similar or...
53
by: Alf P. Steinbach | last post by:
So, I got the itch to write something more... I apologize for not doing more on the attempted "Correct C++ Tutorial" earlier, but there were reasons. This is an UNFINISHED and RAW document,...
42
by: x-pander | last post by:
Is is guaranteed, that a pointer to any object in C points exactly at the lowest addressed byte of this object? Specifcally is it possible for any platform/os/compiler combination that: (char...
1
by: Chathu | last post by:
Hi everyone!.. I'm back and sorry for these idotic questions. I need help on understanding the following program. When I run it I got the answer 2 5, but I can't understand how it is happenning....
39
by: Martin Jřrgensen | last post by:
Hi, I'm relatively new with C-programming and even though I've read about pointers and arrays many times, it's a topic that is a little confusing to me - at least at this moment: ---- 1)...
7
by: phil_w | last post by:
To practice some C I have been looking at the Burrows-Wheeler Transform. Ive got a small program that builds the initial table of possible combinations of the original string, used to find the...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.