Остаточний висновок: арифметика на a void*
є незаконною як для C, так і для C ++.
GCC дозволяє це як розширення, див. Арифметичні вказівки void
- та функціональні покажчики (зверніть увагу, що цей розділ є частиною розділу "Розширення C" цього посібника). Clang та ICC, ймовірно, дозволяють void*
арифметикувати для сумісності з GCC. Інші компілятори (наприклад, MSVC) забороняють вмикати арифметику void*
, а GCC забороняє її, якщо -pedantic-errors
вказано прапор або якщо -Werror-pointer-arith
вказано прапор (цей прапор корисний, якщо ваша база коду також повинна компілюватися з MSVC).
Стандарт C говорить
Цитати взяті з чернетки n1256.
В описі стандарту операції додавання зазначено:
6.5.6-2: Крім того, або обидва операнди мають арифметичний тип, або один операнд є вказівником на тип об'єкта, а інший має цілий тип.
Отже, тут питання void*
полягає в тому, чи є вказівник на "тип об'єкта", або рівнозначно, чи void
"тип об'єкта". Визначенням "тип об'єкта" є:
6.2.5.1: Типи поділяються на типи об'єктів (типи, що повністю описують об'єкти), типи функцій (типи, що описують функції), і неповні типи (типи, що описують об'єкти, але не мають інформації, необхідної для визначення їх розмірів).
А стандарт визначає void
як:
6.2.5-19: void
Тип містить порожній набір значень; це незавершений тип, який неможливо виконати.
Оскільки void
це незавершений тип, це не тип об'єкта. Тому це не є дійсним операндом операції додавання.
Тому ви не можете виконувати арифметику вказівника на void
покажчику.
Примітки
Спочатку вважалося, що void*
арифметика дозволена через такі розділи стандарту С:
6.2.5-27: Вказівник на недійсність повинен мати ті ж
вимоги щодо представлення та вирівнювання , що і вказівник на тип символів.
Однак,
Ті ж
вимоги щодо представлення та вирівнювання мають на увазі взаємозамінність як аргументи до функцій, повернення значень функцій та членів союзів.
Отже, це означає, що printf("%s", x)
має те саме значення, чи x
має тип char*
або void*
, але це не означає, що ви можете робити арифметику на a void*
.
Примітка редактора: Ця відповідь була відредагована для відображення остаточного висновку.