Adding a value that is not unitless to a pointer shall be diagnosed (subject to exceptions below) because this can result in undefined and unexpected behavior.  For example, the operators sizeof and offsetof return a value with unit bytes, the function strlen()} returns a value that is unitless, and the function wcslen() returns a value that is unitless.
A common mistake is to add the size of an array to the array itself (i.e. arrsizeof(arr) or arr + sizeof(arr)).  One correct idiom is to divide the size of the array by the size of the first element in the array, yielding a value that is unitless (i.e., arr[sizeof(arr)/sizeof(arr0)]).
In this noncompliant code example, the pointer buf is added to sizeof(buf), which is clearly incorrect because sizeof(buf) has unit bytes.
| 
int buf[INTBUFSIZE];
int *buf_ptr = buf;
while (havedata && buf_ptr < (buf + sizeof(buf))) {
    *buf_ptr++ = parseint(getdata);
}
 | 
In this noncompliant code example, skip is added to the pointer s, but skip has unit bytes because it contains the result of offsetof.
| 
struct big {
  unsigned long long ull_1; /* typically 8 bytes */
  unsigned long long ull_2; /* typically 8 bytes */
  unsigned long long ull_3; /* typically 8 bytes */
  int si_4; /* typically 4 bytes */
  int si_5; /* typically 4 bytes */
};
/* ... */
size_t skip = offsetof(struct big, ull_2); struct big *s = (struct big *)malloc(sizeof(struct big)); if (!s) {
  /* Handle malloc error */
}
memset(s + skip, 0, sizeof(struct big) - skip);
/* ... */
free(s);
s = NULL;
 | 
In this noncompliant code example, (wcslen(error_msg) - 1) * sizeof(wchar_t) has unit bytes and is added to the pointer error_msg.
| /* ... */ wchar_t error_msg[WCHAR_BUF]; wcscpy(error_msg, "Error: "); fgetws(error_msg + (wcslen(error_msg) - 1) * sizeof(wchar_t), WCHAR_BUF - 7, stdin); /* ... */ | 
EXP408-EX1: Adding a value that is not unitless to a pointer that points to an object that has size 1 need not be diagnosed because this will likely produce the correct result. The following example shows an acceptable use of this exception because (char *)s0 has size 1.
| 
struct big {
  unsigned long long ull_1; /* typically 8 bytes */
  unsigned long long ull_2; /* typically 8 bytes */
  unsigned long long ull_3; /* typically 8 bytes */
  int si_4; /* typically 4 bytes */
  int si_5; /* typically 4 bytes */
};
/* ... */
size_t skip = offsetof(struct big, ull_2); struct big *s = (struct big *)malloc(sizeof(struct big)); if (!s) {
  /* Handle malloc() error */
}
memset((char *)s + skip, 0, sizeof(struct big) - skip);
/* ... */
free(s);
s = NULL;
 | 
| \[[Dowd 06|AA. C References#Dowd 06]\] Chapter 6, "C Language Issues" \[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "HFC Pointer casting and pointer type changes" and "RVG Pointer Arithmetic" \[[MISRA 04|AA. C References#MISRA 04]\] Rules 17.1-17.4 \[[MITRE 07|AA. C References#MITRE 07]\] [CWE ID 468|http://cwe.mitre.org/data/definitions/468.html], "Incorrect Pointer Scaling" \[[Murenin 07|AA. C References#Murenin 07]\] |